X-Git-Url: http://plrg.eecs.uci.edu/git/?p=smartthings-infrastructure.git;a=blobdiff_plain;f=main.groovy;h=b28d935b47563728dc56e7bacdcecfde7c2759a7;hp=e406b84248a0ca0013e123ccc59bf4f78b510c4e;hb=4f9a1209b0c1ca5caf60a0f811e18dde6a92e9e9;hpb=c0cb655866633825464d2af2b572488b0f2e18d0 diff --git a/main.groovy b/main.groovy index e406b84..b28d935 100644 --- a/main.groovy +++ b/main.groovy @@ -3,348 +3,780 @@ 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 Event.Event +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.LocationVar import Location.Phrase -import appTouch.Touch +import appTouch.Touched +import NfcTouch.NfcTouch +import AeonKeyFob.AeonKeyFob +import AeonKeyFob.AeonKeyFobs +import MusicPlayer.MusicPlayer +import MusicPlayer.MusicPlayers +import MotionSensor.MotionSensor +import MotionSensor.MotionSensors +import ImageCapture.ImageCapture +import ImageCapture.ImageCaptures +import SmokeDetector.SmokeDetector +import SmokeDetector.SmokeDetectors +import Alarm.Alarm +import Alarm.Alarms +import SpeechSynthesis.SpeechSynthesis +import SpeechSynthesis.SpeechSynthesises +import Event.Event +import Timer.SimulatedTimer -//GlobalVariables -//create a location object to change the variable inside the class -@Field def location = new locationVar() -//Settings variable defined to settings on purpose -@Field def settings = "Settings" -//Global variable for state[mode] -@Field def state = [home:[],away:[],night:[]] -//Create a global logger object for methods -@Field def log = new Logger() -//Create a global object for app -@Field def app = new Touch(1) -//Create a global list for objects for events on subscribe methods -@Field def ObjectList = [] -//Create a global list for events -@Field def EventList = [] -//Create a global list for function calls based on corresponding events -@Field def FunctionList = [] -//Create a global list for function schedulers -@Field def ListofTimersFunc = [] -//Create a global list for timer schedulers -@Field def ListofTimers = [] +//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) + } + } +} -//ExtractedObjects -//Global Object for class switch! -@Field def switchesoff = new switching(1) +//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(sendEvent) +//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 switcheson = new switching(1) +@Field def switchObject = new Switches(sendEvent, 1) //Global Object for class lock! -@Field def lock1 = new locking(1) -//Global variable for mode! -@Field def newMode = "away" -//Global variable for number! -@Field def waitfor = 5 -//Global Object for functions in subscribe method! -@Field def installed = this.&installed -//Global Object for functions in subscribe method! -@Field def updated = this.&updated -//Global Object for functions in subscribe method! -@Field def appTouch = this.&appTouch +@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) +//Global Object for class aeon key fob! +@Field def aeonKeyFobObject = new AeonKeyFobs(sendEvent, 1) +//Global Object for class music player! +@Field def musicPlayerObject = new MusicPlayers(sendEvent, 1) +//Global Object for class motion sensor! +@Field def motionSensorObject = new MotionSensors(sendEvent, 1) +//Global Object for class image capture! +@Field def imageCaptureObject = new ImageCaptures(sendEvent, 1) +//Global Object for class smoke detector! +@Field def smokeDetectorObject = new SmokeDetectors(sendEvent, 1) +//Global Object for class alarm! +@Field def alarmObject = new Alarms(sendEvent, 1) +//Global Object for class speech synthesis! +@Field def speechSynthesisObject = new SpeechSynthesises(sendEvent, 1) -//Methods -///////////////////////////////////////////////////////////////////// -def definition(LinkedHashMap LHM) { - println("IGNORE -- JUST SOME DEFINITION") -} +//Application #1 +class App1 { + def reference + def location + def app -///////////////////////////////////////////////////////////////////// -def preferences(Closure Input) { - println("IGNORE -- JUST SOME DEFINITION") -} -///////////////////////////////////////////////////////////////////// -def setLocationMode(String mode) { - location.mode = mode -} + //Extracted objects for App1 + //Object for class switch! + def switches + //Object for class thermostat! + def thermostats + //Object for class lock! + def locks -///////////////////////////////////////////////////////////////////// -////subscribe(app, func) -def subscribe(Object Obj, Closure Input) { - ObjectList.add(Obj) - EventList.add("Touched") - FunctionList.add(Input) -} -////subscribe(obj, string, func) -def subscribe(Object Obj, String S, Closure Input) { - ObjectList.add(Obj) - EventList.add(S) - FunctionList.add(Input) -} -////subscribe(obj, string, func, hashmap) -def subscribe(Object Obj, String S, Closure Input, LinkedHashMap LHM) { - ObjectList.add(Obj) - EventList.add(S) - FunctionList.add(Input) -} -///////////////////////////////////////////////////////////////////// -def EventHandler() { - while(true) { - List evt = [] - print "Waiting for an event...\n" - def EVENT = System.in.newReader().readLine() - SepLine = EVENT.split() - for (int i = 0; i < EventList.size(); i++) { - if (EventList[i] == SepLine[0]) { - println("The following effect: \n") - evt.add(new Event()) - switch(SepLine[0]) { - case "Touched": - ObjectList[i].touched = 1 - evt[-1].value = "Touched" - evt[-1].linkText = "touched by user" - evt[-1].name = "TouchSensor" - evt[-1].descriptionText = "Touching" - break - case "lock": - if (SepLine[1] == "0") { - ObjectList[i][0].lock() - evt[-1].deviceId = 0 - evt[-1].value = "locked" - evt[-1].linkText = "lock0" - evt[-1].displayName = "lock0" - evt[-1].name = "lock" - evt[-1].descriptionText = "locking" - } else if (SepLine[1] == "1") { - ObjectList[i][1].lock() - evt[-1].deviceId = 1 - evt[-1].value = "locked" - evt[-1].linkText = "lock1" - evt[-1].displayName = "lock1" - evt[-1].name = "lock" - evt[-1].descriptionText = "locking" - } else if (SepLine[1] == "2") { - ObjectList[i][2].lock() - evt[-1].deviceId = 2 - evt[-1].value = "locked" - evt[-1].linkText = "lock2" - evt[-1].displayName = "lock2" - evt[-1].name = "lock" - evt[-1].descriptionText = "locking" - } - break - case "unlock": - if (SepLine[1] == "0") { - ObjectList[i][0].unlock() - evt[-1].deviceId = 0 - evt[-1].value = "unlocked" - evt[-1].linkText = "lock0" - evt[-1].displayName = "lock0" - evt[-1].name = "lock" - evt[-1].descriptionText = "unlocking" - } else if (SepLine[1] == "1") { - ObjectList[i][1].unlock() - evt[-1].deviceId = 0 - evt[-1].value = "unlocked" - evt[-1].linkText = "lock1" - evt[-1].displayName = "lock1" - evt[-1].name = "lock" - evt[-1].descriptionText = "unlocking" - } else if (SepLine[1] == "2") { - ObjectList[i][2].unlock() - evt[-1].deviceId = 2 - evt[-1].value = "unlocked" - evt[-1].linkText = "lock2" - evt[-1].displayName = "lock2" - evt[-1].name = "lock" - evt[-1].descriptionText = "unlocking" - } - break - case "contact.open": - if (SepLine[1] == "0") { - ObjectList[i][0].contactLatestValue = ObjectList[i].currentContact - ObjectList[i][0].currentContact = "open" - evt[-1].deviceId = 0 - evt[-1].value = "contact.open" - evt[-1].linkText = "contact0" - evt[-1].displayName = "contact0" - evt[-1].name = "ContactSensor" - evt[-1].descriptionText = "opening" - } else if (SepLine[1] == "1") { - ObjectList[i][1].contactLatestValue = ObjectList[i].currentContact - ObjectList[i][1].currentContact = "open" - evt[-1].deviceId = 1 - evt[-1].value = "contact.open" - evt[-1].linkText = "contact1" - evt[-1].displayName = "contact1" - evt[-1].name = "ContactSensor" - evt[-1].descriptionText = "opening" - } else if (SepLine[1] == "2") { - ObjectList[i][2].contactLatestValue = ObjectList[i].currentContact - ObjectList[i][2].currentContact = "open" - evt[-1].deviceId = 2 - evt[-1].value = "contact.open" - evt[-1].linkText = "contact2" - evt[-1].displayName = "contact2" - evt[-1].name = "ContactSensor" - evt[-1].descriptionText = "opening" - } - break - case "contact.closed": - if (SepLine[1] == "0") { - ObjectList[i][0].contactLatestValue = ObjectList[i].currentContact - ObjectList[i][0].currentContact = "closed" - evt[-1].deviceId = 0 - evt[-1].value = "contact.closed" - evt[-1].linkText = "contact0" - evt[-1].displayName = "contact0" - evt[-1].name = "ContactSensor" - evt[-1].descriptionText = "closing" - } else if (SepLine[1] == "1") { - ObjectList[i][1].contactLatestValue = ObjectList[i].currentContact - ObjectList[i][1].currentContact = "closed" - evt[-1].deviceId = 1 - evt[-1].value = "contact.closed" - evt[-1].linkText = "contact1" - evt[-1].displayName = "contact1" - evt[-1].name = "ContactSensor" - evt[-1].descriptionText = "closing" - } else if (SepLine[1] == "2") { - ObjectList[i][2].contactLatestValue = ObjectList[i].currentContact - ObjectList[i][2].currentContact = "closed" - evt[-1].deviceId = 2 - evt[-1].value = "contact.closed" - evt[-1].linkText = "contact2" - evt[-1].displayName = "contact2" - evt[-1].name = "ContactSensor" - evt[-1].descriptionText = "closing" - } - break - default: - break - } - FunctionList[i](evt[-1]) + //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 appTouch = this.&appTouch + //Global Object for functions in subscribe method! + def changedLocationMode = this.&changedLocationMode + //Global Object for functions in subscribe method! + def restoreState = this.&restoreState + //Global Object for functions in subscribe method! + def saveState = this.&saveState + //Global Object for functions in subscribe method! + def getCurrentMode = this.&getCurrentMode + + App1(Object obj) { + reference = obj + location = obj.locationObject + app = obj.appObject + switches = obj.switchObject + thermostats = obj.thermostatObject + locks = obj.lockObject + //Global variable for settings! + settings = [app:app, switches:switches, thermostats:thermostats, locks:locks] + } + //Global variables for each app + //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 = [] + //Create a global variable for settings + def settings + //Zip code + def zipCode = 92617 + + //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*0, functionToCall) + } else { + timersFuncList.add(functionToCall) + timersList.add(new SimulatedTimer()) + def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds*0, functionToCall) + } + } + + def runIn(int seconds, Closure functionToCall, LinkedHashMap metaData) { + runIn(seconds, functionToCall) + } + + def runIn(int seconds, String nameOfFunction, LinkedHashMap metaData) { + runIn(seconds, nameOfFunction) + } + + def runIn(int seconds, String nameOfFunction) { + timersFuncList.add(nameOfFunction) + timersList.add(new SimulatedTimer()) + def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(seconds*1000*0) { + "$nameOfFunction"() + } + } + ///////////////////////////////////////////////////////////////////// + ////unschedule(func) + def unschedule(Closure functionToUnschedule) { + for (int i = 0;i < timersFuncList.size();i++) { + if (timersFuncList[i] == functionToUnschedule) { + if (timersList != null) + timersList[i].cancel() } } } -} -///////////////////////////////////////////////////////////////////// -////runIn(time, func) -def runIn(int seconds, Closure Input) { - ListofTimersFunc.add(Input) - ListofTimers.add(new Timer()) - def task = ListofTimers[-1].runAfter(1000*seconds, Input) -} -///////////////////////////////////////////////////////////////////// -////unschedule(func) -def unschedule(Closure Input) { - for (int i = 0;i < ListofTimersFunc.size();i++) { - if (ListofTimersFunc[i] == Input) { - ListofTimers[i].cancel() + + + def unschedule() { + for (int i = 0;i < timersFuncList.size();i++) { + if (timersList != null) + timersList[i].cancel() } } -} -///////////////////////////////////////////////////////////////////// -////sendNotificationToContacts(text, recipients) -def sendNotificationToContacts(String S, List 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 \""+S+"\" to "+location.PhoneNums[j].toString()) + ///////////////////////////////////////////////////////////////////// + ////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()) + } } } } -} -///////////////////////////////////////////////////////////////////// -////sendNotificationToContacts(text, recipients) -def sendSms(long Phone, String S) { - println("Sending \""+S+"\" to "+Phone.toString()) -} + ///////////////////////////////////////////////////////////////////// + ////sendSms(phone, text) + def sendSms(long phoneNumber, String text) { + println("Sending \""+text+"\" to "+phoneNumber.toString()) + } + + 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*0) { + "$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*0, nameOfFunction) + } else { + timersFuncList.add(nameOfFunction) + timersList.add(new SimulatedTimer()) + def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds*0, nameOfFunction) + } + } + ///////////////////////////////////////////////////////////////////// + def now() { + return System.currentTimeMillis() + } + ///////////////////////////////////////////////////////////////////// + def getTemperatureScale() { + return 'C' //Celsius for now + } + + ///////////////////////////////////////////////////////////////////// + def getSunriseAndSunset(LinkedHashMap metaData) { + def sunRiseSetInfo = [sunrise:[time:1563800160000],sunset:[time:1563850740000]] + return sunRiseSetInfo + } -/** - * Good Night House - * - * Copyright 2014 Joseph Charette - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License - * for the specific language governing permissions and limitations under the License. - * - */ -definition( - name: "Good Night House", - namespace: "charette.joseph@gmail.com", - author: "Joseph Charette", - description: "Some on, some off with delay for bedtime, Lock The Doors", - category: "Convenience", - iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", - iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png" -/** -* Borrowed code from -* Walk Gentle Into That Good Night -* -* Author: oneaccttorulethehouse@gmail.com -* Date: 2014-02-01 - */ - ) -preferences { - section("When I touch the app turn these lights off…"){ - input "switchesoff", "capability.switch", multiple: true, required:true - } - section("When I touch the app turn these lights on…"){ - input "switcheson", "capability.switch", multiple: true, required:false - } - section("Lock theses locks...") { - input "lock1","capability.lock", multiple: true - } - section("And change to this mode...") { - input "newMode", "mode", title: "Mode?" - } - section("After so many seconds (optional)"){ - input "waitfor", "number", title: "Off after (default 120)", required: true + def installed() { + subscribe(location, changedLocationMode) + subscribe(app, appTouch) + saveState() + } + + def updated() { + unsubscribe() + subscribe(location, changedLocationMode) + subscribe(app, appTouch) + saveState() + } + + def appTouch(evt) + { + restoreState(currentMode) + } + + def changedLocationMode(evt) + { + restoreState(evt.value) + } + + private restoreState(mode) + { + log.info "restoring state for mode '$mode'" + def map = state[mode] ?: [:] + switches?.each { + def value = map[it.id] + if (value?.switch == "on") { + def level = value.level + if (level) { + log.debug "setting $it.label level to $level" + it.setLevel(level) + } + else { + log.debug "turning $it.label on" + it.on() + } + } + else if (value?.switch == "off") { + log.debug "turning $it.label off" + it.off() + } + } + + thermostats?.each { + def value = map[it.id] + if (value?.coolingSetpoint) { + log.debug "coolingSetpoint = $value.coolingSetpoint" + it.setCoolingSetpoint(value.coolingSetpoint) + } + if (value?.heatingSetpoint) { + log.debug "heatingSetpoint = $value.heatingSetpoint" + it.setHeatingSetpoint(value.heatingSetpoint) + } + } + + locks?.each { + def value = map[it.id] + if (value) { + if (value?.locked) { + it.lock() + } + else { + it.unlock() + } + } + } + } + + + private saveState() + { + def mode = currentMode + def map = state[mode] ?: [:] + + switches?.each { + map[it.id] = [switch: it.currentSwitch, level: it.currentLevel] + } + + thermostats?.each { + map[it.id] = [coolingSetpoint: it.currentCoolingSetpoint, heatingSetpoint: it.currentHeatingSetpoint] + } + + locks?.each { + map[it.id] = [locked: it.currentLock == "locked"] + } + + state[mode] = map + log.debug "saved state for mode ${mode}: ${state[mode]}" + log.debug "state: $state" + } + + private getCurrentMode() + { + location.mode ?: "_none_" } } -def installed() -{ - log.debug "Installed with settings: ${settings}" - log.debug "Current mode = ${location.mode}" - subscribe(app, appTouch) -} +//Application #2 +class App2 { + def reference + def location + def app + //Extracted objects for App2 + //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 = "Yes" + //Global variable for enum! + def masterLock = "Yes" + //Global variable for enum! + def masterDoor = "No" -def updated() -{ - log.debug "Updated with settings: ${settings}" - log.debug "Current mode = ${location.mode}" - unsubscribe() - subscribe(app, appTouch) -} + //Extracted objects for functions for App2 + //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 touchHandler = this.&touchHandler + + App2(Object obj) { + reference = obj + location = obj.locationObject + app = obj.appObject + tag = obj.touchSensorObject + switch1 = obj.switchObject + lock = obj.lockObject + garageDoor = obj.doorControlObject + //Global variable for settings! + settings = [app:app, tag:tag, switch1:switch1, lock:lock, garageDoor:garageDoor, masterSwitch:masterSwitch, masterLock:masterLock, masterDoor:masterDoor] + } + //Global variables for each app + //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 = [] + //Create a global variable for settings + def settings + //Zip code + def zipCode = 92617 + + //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*0, functionToCall) + } else { + timersFuncList.add(functionToCall) + timersList.add(new SimulatedTimer()) + def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds*0, functionToCall) + } + } + + def runIn(int seconds, Closure functionToCall, LinkedHashMap metaData) { + runIn(seconds, functionToCall) + } + + def runIn(int seconds, String nameOfFunction, LinkedHashMap metaData) { + runIn(seconds, nameOfFunction) + } + + def runIn(int seconds, String nameOfFunction) { + timersFuncList.add(nameOfFunction) + timersList.add(new SimulatedTimer()) + def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(seconds*1000*0) { + "$nameOfFunction"() + } + } + ///////////////////////////////////////////////////////////////////// + ////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()) + } + + 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*0) { + "$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*0, nameOfFunction) + } else { + timersFuncList.add(nameOfFunction) + timersList.add(new SimulatedTimer()) + def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds*0, nameOfFunction) + } + } + ///////////////////////////////////////////////////////////////////// + def now() { + return System.currentTimeMillis() + } + ///////////////////////////////////////////////////////////////////// + def getTemperatureScale() { + return 'C' //Celsius for now + } + + ///////////////////////////////////////////////////////////////////// + def getSunriseAndSunset(LinkedHashMap metaData) { + def sunRiseSetInfo = [sunrise:[time:1563800160000],sunset:[time:1563850740000]] + return sunRiseSetInfo + } -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) + 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() + } + } + } + } } -installed() -EventHandler() +@Field def app1 = new App1(this) +@Field def app2 = new App2(this) +app1.installed() +app2.installed() + +appObject.setValue([name: "nfcTouch", value: "touched", deviceId: "nfcSensorID0", descriptionText: "", +displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]]) +appObject.setValue([name: "Touched", value: "touched", deviceId: "touchedSensorID0", descriptionText: "", +displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]]) +locationObject.setValue([name: "Location", value: "away", deviceId: "locationID0", descriptionText: "", +displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]]) +locationObject.setValue([name: "Location", value: "home", deviceId: "locationID0", descriptionText: "", +displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]]) +locationObject.setValue([name: "Location", value: "night", deviceId: "locationID0", descriptionText: "", +displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])