X-Git-Url: http://plrg.eecs.uci.edu/git/?p=smartthings-infrastructure.git;a=blobdiff_plain;f=main.groovy;fp=main.groovy;h=b28d935b47563728dc56e7bacdcecfde7c2759a7;hp=54605116eadba871d6e24cf2164acc84236ad0e4;hb=16ebbcf5da0fa9989acb5b03129b9706331066c5;hpb=83c29285fc443d05c449cab55f5dbef8fb942447 diff --git a/main.groovy b/main.groovy index 5460511..b28d935 100644 --- a/main.groovy +++ b/main.groovy @@ -24,11 +24,19 @@ 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 -import gov.nasa.jpf.vm.Verify - //Global eventHandler ///////////////////////////////////////////////////////////////////// def eventHandler(LinkedHashMap eventDataMap) { @@ -65,7 +73,7 @@ def eventHandler(LinkedHashMap eventDataMap) { eventHandler(eventDataMap) } //Object for location -@Field def locationObject = new LocationVar() +@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 @@ -88,6 +96,16 @@ def eventHandler(LinkedHashMap eventDataMap) { @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) //Application #1 class App1 { @@ -96,12 +114,12 @@ class App1 { def app //Extracted objects for App1 + //Object for class switch! + def switches + //Object for class thermostat! + def thermostats //Object for class lock! - def lock1 - //Global variable for number! - def minutesLater = 1 - //Object for class contactSensor! - def openSensor + def locks //Extracted objects for functions for App1 //Global Object for functions in subscribe method! @@ -109,24 +127,25 @@ class App1 { //Global Object for functions in subscribe method! def updated = this.&updated //Global Object for functions in subscribe method! - def initialize = this.&initialize + def appTouch = this.&appTouch //Global Object for functions in subscribe method! - def lockDoor = this.&lockDoor + def changedLocationMode = this.&changedLocationMode //Global Object for functions in subscribe method! - def doorOpen = this.&doorOpen + def restoreState = this.&restoreState //Global Object for functions in subscribe method! - def doorClosed = this.&doorClosed + def saveState = this.&saveState //Global Object for functions in subscribe method! - def doorHandler = this.&doorHandler + def getCurrentMode = this.&getCurrentMode App1(Object obj) { reference = obj location = obj.locationObject app = obj.appObject - lock1 = obj.lockObject - openSensor = obj.contactObject + switches = obj.switchObject + thermostats = obj.thermostatObject + locks = obj.lockObject //Global variable for settings! - settings = [app:app, lock1:lock1, minutesLater:minutesLater, openSensor:openSensor] + settings = [app:app, switches:switches, thermostats:thermostats, locks:locks] } //Global variables for each app //Global variable for state[mode] @@ -145,6 +164,8 @@ class App1 { def timersList = [] //Create a global variable for settings def settings + //Zip code + def zipCode = 92617 //Methods ///////////////////////////////////////////////////////////////////// @@ -182,11 +203,27 @@ class App1 { 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) + 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, functionToCall) + 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"() } } ///////////////////////////////////////////////////////////////////// @@ -223,6 +260,10 @@ class App1 { 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) { @@ -248,7 +289,7 @@ class App1 { timersFuncList.add(nameOfFunction) timersList.add(new SimulatedTimer()) - def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*1000) { + def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*1000*0) { "$nameOfFunction"() } } @@ -271,80 +312,125 @@ class App1 { if (timersFuncList.contains(nameOfFunction)) { timersList[timersFuncList.indexOf(nameOfFunction)].cancel() - def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds, nameOfFunction) + 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, nameOfFunction) + 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 installed() - { - log.debug "Auto Lock Door installed. (URL: http://www.github.com/smartthings-users/smartapp.auto-lock-door)" - initialize() + def installed() { + subscribe(location, changedLocationMode) + subscribe(app, appTouch) + saveState() } - def updated() - { - unsubscribe() - unschedule() - log.debug "Auto Lock Door updated." - initialize() + def updated() { + unsubscribe() + subscribe(location, changedLocationMode) + subscribe(app, appTouch) + saveState() } - def initialize() + def appTouch(evt) { - log.debug "Settings: ${settings}" - subscribe(lock1, "lock", doorHandler) - subscribe(openSensor, "contact.closed", doorClosed) - subscribe(openSensor, "contact.open", doorOpen) + restoreState(currentMode) } - def lockDoor() + def changedLocationMode(evt) { - log.debug "Locking Door if Closed" - if((openSensor.latestValue("contact") == "closed")){ - log.debug "Door Closed" - lock1.lock() - } else { - if ((openSensor.latestValue("contact") == "open")) { - def delay = minutesLater * 60 - log.debug "Door open will try again in $minutesLater minutes" - runIn( delay, lockDoor ) - } - } + restoreState(evt.value) } - def doorOpen(evt) { - log.debug "Door open reset previous lock task..." - unschedule( lockDoor ) - def delay = minutesLater * 60 - runIn( delay, lockDoor ) - } + 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) + } + } - def doorClosed(evt) { - log.debug "Door Closed" + locks?.each { + def value = map[it.id] + if (value) { + if (value?.locked) { + it.lock() + } + else { + it.unlock() + } + } + } } - def doorHandler(evt) + + private saveState() { - log.debug "Door ${openSensor.latestValue}" - log.debug "Lock ${evt.name} is ${evt.value}." + def mode = currentMode + def map = state[mode] ?: [:] - if (evt.value == "locked") { // If the human locks the door then... - log.debug "Cancelling previous lock task..." - unschedule( lockDoor ) // ...we don't need to lock it later. - } - else { // If the door is unlocked then... - def delay = minutesLater * 60 // runIn uses seconds - log.debug "Re-arming lock in ${minutesLater} minutes (${delay}s)." - runIn( delay, lockDoor ) // ...schedule to lock in x minutes. - } + 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_" } } @@ -365,11 +451,11 @@ class App2 { //Object for class door control! def garageDoor //Global variable for enum! - def masterSwitch = "switchID0" + def masterSwitch = "Yes" //Global variable for enum! - def masterLock = "lockID0" + def masterLock = "Yes" //Global variable for enum! - def masterDoor = "DoorControlID0" + def masterDoor = "No" //Extracted objects for functions for App2 //Global Object for functions in subscribe method! @@ -381,8 +467,6 @@ class App2 { //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 App2(Object obj) { @@ -413,6 +497,8 @@ class App2 { def timersList = [] //Create a global variable for settings def settings + //Zip code + def zipCode = 92617 //Methods ///////////////////////////////////////////////////////////////////// @@ -450,11 +536,27 @@ class App2 { 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) + 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, functionToCall) + 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"() } } ///////////////////////////////////////////////////////////////////// @@ -491,6 +593,10 @@ class App2 { 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) { @@ -511,7 +617,7 @@ class App2 { timersFuncList.add(nameOfFunction) timersList.add(new SimulatedTimer()) - def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*1000) { + def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*1000*0) { "$nameOfFunction"() } } @@ -534,22 +640,36 @@ class App2 { if (timersFuncList.contains(nameOfFunction)) { timersList[timersFuncList.indexOf(nameOfFunction)].cancel() - def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds, nameOfFunction) + 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, nameOfFunction) + 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 pageTwo() { dynamicPage(name: "pageTwo") { - section("If set, the state of these devices will be toggled each time the tag is touched, " + + 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 } @@ -558,12 +678,12 @@ class App2 { } 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 - } + } } } @@ -618,7 +738,7 @@ class App2 { } } } - + if (lock) { def status = currentStatus(lock, masterLock, "lock") lock.each { @@ -630,7 +750,7 @@ class App2 { } } } - + if (garageDoor) { def status = currentStatus(garageDoor, masterDoor, "status") garageDoor.each { @@ -650,48 +770,13 @@ class App2 { 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 - } -} +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"]])