X-Git-Url: http://plrg.eecs.uci.edu/git/?p=smartthings-infrastructure.git;a=blobdiff_plain;f=main.groovy;h=d8f3667539d5a478345ea263835084017281e3a6;hp=299e6e4a40c52832e9c5c093de3afed0f26127cd;hb=bab74a20e94efd87e5d055847ea8e4dfdb8a1790;hpb=285570e387d51040a4c14ac604a6cc6ea68e0f9d diff --git a/main.groovy b/main.groovy index 299e6e4..d8f3667 100644 --- a/main.groovy +++ b/main.groovy @@ -3,36 +3,109 @@ import groovy.transform.Field //Importing Classes -import ContactSensor.Contacting -import ContactSensor.Contacts -import Lock.Locking +import ContactSensor.ContactSensor +import ContactSensor.ContactSensors +import DoorControl.DoorControl +import DoorControl.DoorControls +import Lock.Lock import Lock.Locks -import Switch.Switching +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 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 + +//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 -> - app1.eventHandler(eventDataMap) - app2.eventHandler(eventDataMap) + eventHandler(eventDataMap) } //Object for location -@Field def locationObject = new LocationVar() -//Object for touch +@Field def locationObject = new LocationVar(sendEvent) +//Object for touch to call function @Field def appObject = new Touched(sendEvent, 0) - -//Extracted global objects for both Apps +//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 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, 2) +@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) //Application #1 class App1 { @@ -41,41 +114,39 @@ class App1 { def app //Extracted objects for App1 + //Global variable for time! + def time = "15:00" //Object for class lock! - def lock1 + def lock //Object for class contactSensor! def contact - //Global variable for number! - def minutesLater = 1 - //Global variable for number! - def secondsLater = 2 - //Global variable for recipients! - def recipients = ['AJ'] - //Global variable for phone number! - def phoneNumber = 9495379373 + //Global variable for enum! + def sendPushMessage = "Yes" + //Global variable for phone! + def phone = 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 + def setTimeCallback = this.&setTimeCallback //Global Object for functions in subscribe method! - def unlockDoor = this.&unlockDoor + def doorOpenCheck = this.&doorOpenCheck //Global Object for functions in subscribe method! - def doorHandler = this.&doorHandler + def lockMessage = this.&lockMessage App1(Object obj) { reference = obj location = obj.locationObject app = obj.appObject - lock1 = obj.lockObject + lock = obj.lockObject contact = obj.contactObject + //Global variable for settings! + settings = [app:app, time:time, lock:lock, contact:contact, sendPushMessage:sendPushMessage, phone:phone] } //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 @@ -90,8 +161,10 @@ class App1 { def timersFuncList = [] //Create a global list for timer schedulers def timersList = [] - //Create a global list for events - def evt = [] + //Create a global variable for settings + def settings + //Zip code + def zipCode = 92617 //Methods ///////////////////////////////////////////////////////////////////// @@ -102,9 +175,15 @@ class App1 { ///////////////////////////////////////////////////////////////////// ////subscribe(obj, func) def subscribe(Object obj, Closure FunctionToCall) { - objectList.add(obj) - eventList.add("Touched") - functionList.add(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) { @@ -121,22 +200,52 @@ class App1 { ///////////////////////////////////////////////////////////////////// ////runIn(time, func) def runIn(int seconds, Closure functionToCall) { - timersFuncList.add(functionToCall) - timersList.add(new Timer()) - def task = timersList[-1].runAfter(1000*seconds, 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) { - timersList[i].cancel() + 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, List 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]) { @@ -150,120 +259,124 @@ 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()) + } ///////////////////////////////////////////////////////////////////// - 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 < eventList.size();i++) { - if (eventList[i] == name) { - evt.add(new Event()) - evt[-1].value = value - evt[-1].name = name - evt[-1].deviceId = deviceId - evt[-1].descriptionText = descriptionText - evt[-1].displayed = displayed - evt[-1].linkText = linkText - evt[-1].displayName = linkText - evt[-1].isStateChange = isStateChange - evt[-1].unit = unit - evt[-1].data = data - functionList[i](evt[-1]) - } + ////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"() } } - - def installed(){ - initialize() + ////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 updated(){ - unsubscribe() - unschedule() - initialize() + ///////////////////////////////////////////////////////////////////// + def getSunriseAndSunset(LinkedHashMap metaData) { + def sunRiseSetInfo = [sunrise:[time:1563800160000],sunset:[time:1563850740000]] + return sunRiseSetInfo } + + def installed() { + schedule(time, "setTimeCallback") - 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 updated(settings) { + unschedule() + schedule(time, "setTimeCallback") } - 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) - } + def setTimeCallback() { + if (contact) { + doorOpenCheck() + } else { + lockMessage() + lock.lock() + } + } + def doorOpenCheck() { + def currentState = contact.contactState + if (currentState?.value == "open") { + def msg = "${contact.displayName} is open. Scheduled lock failed." + log.info msg + if (sendPushMessage) { + sendPush msg } - if ( phoneNumber ) { - log.debug("Sending text message...") - sendSms( phoneNumber, "${lock1} unlocked after ${contact} was opened for ${secondsLater} seconds!") + if (phone) { + sendSms phone, msg } + } else { + lockMessage() + lock.lock() + } } - 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!") - } - } + def lockMessage() { + def msg = "Locking ${lock.displayName} due to scheduled lock." + log.info msg + if (sendPushMessage) { + sendPush msg + } + if (phone) { + sendSms phone, msg + } } } @@ -275,34 +388,45 @@ class App2 { def app //Extracted objects for App2 - //Object for class Switch! - def switchesoff - //Object for class Switch! - def switcheson + //Object for class Touch Sensor! + def tag + //Object for class switch! + def switch1 //Object for class lock! - def lock1 - //Global variable for mode! - def newMode = "away" - //Global variable for number! - def waitfor = 10 + 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 = "Yes" + + //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 appTouch = this.&appTouch + 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 - switchesoff = obj.switchObject - switcheson = obj.switchObject - lock1 = obj.lockObject + 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 - //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 @@ -317,8 +441,10 @@ class App2 { def timersFuncList = [] //Create a global list for timer schedulers def timersList = [] - //Create a global list for events - def evt = [] + //Create a global variable for settings + def settings + //Zip code + def zipCode = 92617 //Methods ///////////////////////////////////////////////////////////////////// @@ -329,9 +455,15 @@ class App2 { ///////////////////////////////////////////////////////////////////// ////subscribe(obj, func) def subscribe(Object obj, Closure FunctionToCall) { - objectList.add(obj) - eventList.add("Touched") - functionList.add(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) { @@ -348,22 +480,52 @@ class App2 { ///////////////////////////////////////////////////////////////////// ////runIn(time, func) def runIn(int seconds, Closure functionToCall) { - timersFuncList.add(functionToCall) - timersList.add(new Timer()) - def task = timersList[-1].runAfter(1000*seconds, 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) { - timersList[i].cancel() + 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, List 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]) { @@ -377,65 +539,175 @@ 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()) + } ///////////////////////////////////////////////////////////////////// - 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 < eventList.size();i++) { - if (eventList[i] == name) { - evt.add(new Event()) - evt[-1].value = value - evt[-1].name = name - evt[-1].deviceId = deviceId - evt[-1].descriptionText = descriptionText - evt[-1].displayed = displayed - evt[-1].linkText = linkText - evt[-1].displayName = linkText - evt[-1].isStateChange = isStateChange - evt[-1].unit = unit - evt[-1].data = data - functionList[i](evt[-1]) - } + ////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 installed() - { - log.debug "Installed with settings: ${settings}" - log.debug "Current mode = ${location.mode}" - subscribe(app, appTouch) + 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() - { + 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) + 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() + } + } + } } } @@ -443,3 +715,4 @@ class App2 { @Field def app2 = new App2(this) app1.installed() app2.installed() +