mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-13 05:11:51 +00:00
MSA-1570: This SmartApp allows you to turn on switches triggered by arrivals, contacts opening or motion. The app will only turn on switches that are not on already and turn off those switches after an amount of time set by the user. This way if you have a light on already, it won't turn off when this SmartApp is triggered. I looked around and didn't see any other SmartApps that did this.
This commit is contained in:
238
smartapps/js/switch-timer.src/switch-timer.groovy
Normal file
238
smartapps/js/switch-timer.src/switch-timer.groovy
Normal file
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* Switch Timer
|
||||
*
|
||||
* Copyright 2016 Joe Saporito
|
||||
*
|
||||
* 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: "Switch Timer",
|
||||
namespace: "js",
|
||||
author: "Joe Saporito",
|
||||
description: "Turns on switches that are not already on for a determined amount of time after an event. ",
|
||||
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",
|
||||
iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")
|
||||
|
||||
|
||||
preferences {
|
||||
|
||||
page(name: "settings")
|
||||
page(name: "certainTime")
|
||||
page(name: "renameLabel")
|
||||
}
|
||||
|
||||
def settings() {
|
||||
dynamicPage(name: "settings", title: "Turn switches off after some minutes, unless already on", uninstall: true, install: true) {
|
||||
section("Choose one or more, when..."){
|
||||
input "people", "capability.presenceSensor", title: "Arrival Of", required: false, multiple: true
|
||||
input "doors", "capability.contactSensor", title: "Doors", required: false, multiple: true
|
||||
input "motion", "capability.motionSensor", title: "Motion Here", required: false, multiple: true
|
||||
}
|
||||
section("Turn on switches"){
|
||||
input "switches", "capability.switch", multiple: true, required: true
|
||||
}
|
||||
section("Turn off after") {
|
||||
input "waitTime", "decimal", title: "Minutes", required: true
|
||||
}
|
||||
section(title: "Additional Options") {
|
||||
def timeLabel = timeIntervalLabel()
|
||||
href "certainTime", title: "Only during a certain time", description: timeLabel ?: "Tap to set", state: timeLabel ? "complete" : null
|
||||
def appLabel = getDefaultLabel()
|
||||
href "renameLabel", title: "Rename '" + appLabel + "'", description: ""
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def certainTime() {
|
||||
dynamicPage(name:"certainTime",title: "Only during a certain time", uninstall: false) {
|
||||
section() {
|
||||
input "startEnum", "enum", title: "Starting at", options: ["A specific time", "Sunrise", "Sunset"], defaultValue: "A specific time", submitOnChange: true
|
||||
if(startEnum in [null, "A specific time"]) input "startTime", "time", title: "Start time", required: false
|
||||
else {
|
||||
if(startEnum == "Sunrise") input "startSunriseOffset", "number", range: "*..*", title: "Offset in minutes (+/-)", required: false
|
||||
else if(startEnum == "Sunset") input "startSunsetOffset", "number", range: "*..*", title: "Offset in minutes (+/-)", required: false
|
||||
}
|
||||
}
|
||||
|
||||
section() {
|
||||
input "endEnum", "enum", title: "Ending at", options: ["A specific time", "Sunrise", "Sunset"], defaultValue: "A specific time", submitOnChange: true
|
||||
if(endEnum in [null, "A specific time"]) input "endTime", "time", title: "End time", required: false
|
||||
else {
|
||||
if(endEnum == "Sunrise") input "endSunriseOffset", "number", range: "*..*", title: "Offset in minutes (+/-)", required: false
|
||||
else if(endEnum == "Sunset") input "endSunsetOffset", "number", range: "*..*", title: "Offset in minutes (+/-)", required: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def renameLabel() {
|
||||
dynamicPage(name:"renameLabel",title: "Rename", uninstall: false) {
|
||||
section() {
|
||||
input "appLabelText", "text", title: "Rename to", defaultValue: (appLabelText ? appLabelText : getDefaultLabel()), required: false
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def installed() {
|
||||
log.debug "Installed with settings: ${settings}"
|
||||
|
||||
initialize()
|
||||
updateLabel()
|
||||
}
|
||||
|
||||
def updated() {
|
||||
log.debug "Updated with settings: ${settings}"
|
||||
unsubscribe()
|
||||
initialize()
|
||||
updateLabel()
|
||||
}
|
||||
|
||||
def initialize() {
|
||||
subscribeToEvents()
|
||||
}
|
||||
|
||||
def subscribeToEvents() {
|
||||
subscribe(doors, "contact.open", activateHandler)
|
||||
subscribe(people, "presence.present", activateHandler)
|
||||
subscribe(motion, "motion.active", activateHandler)
|
||||
}
|
||||
|
||||
// TODO: implement event handlers
|
||||
def activateHandler(evt) {
|
||||
if (checkTime()) {
|
||||
log.trace("$evt.name triggered")
|
||||
turnOn()
|
||||
}
|
||||
}
|
||||
|
||||
def turnOn() {
|
||||
if(state.offSwitches) {
|
||||
runIn(waitTime * 60, turnOff)
|
||||
return
|
||||
}
|
||||
def offSwitches = getOffSwitches()
|
||||
for (s in offSwitches) {
|
||||
s.on()
|
||||
}
|
||||
if (offSwitches.size() > 0) {
|
||||
state.offSwitches = offSwitches.displayName
|
||||
runIn(waitTime * 60, turnOff)
|
||||
}
|
||||
}
|
||||
|
||||
def turnOff() {
|
||||
if (state.offSwitches) {
|
||||
def offSwitches = switches.findAll {
|
||||
it.displayName in state.offSwitches
|
||||
}
|
||||
for (s in offSwitches) {
|
||||
s.off()
|
||||
}
|
||||
state.offSwitches = null
|
||||
}
|
||||
}
|
||||
|
||||
def updateLabel() {
|
||||
if (appLabelText) {
|
||||
if (appLabelText != app.label) {
|
||||
log.trace("Renamed to $appLabelText")
|
||||
app.updateLabel(appLabelText)
|
||||
}
|
||||
}
|
||||
else {
|
||||
def label = getDefaultLabel()
|
||||
log.trace("Renamed to $label")
|
||||
app.updateLabel(label)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private getDefaultLabel() {
|
||||
def label = "Switch Timer"
|
||||
|
||||
if (switches) {
|
||||
label = "Timer for " + switches[0].displayName
|
||||
}
|
||||
|
||||
return label
|
||||
}
|
||||
|
||||
private getOffSwitches() {
|
||||
def offSwitches = switches.findAll {
|
||||
it.currentSwitch == "off" ||
|
||||
it.currentSwitch == null
|
||||
}
|
||||
return offSwitches
|
||||
}
|
||||
private checkTime() {
|
||||
def result = true
|
||||
|
||||
if ((startTime && endTime) ||
|
||||
(startTime && endEnum in ["Sunrise", "Sunset"]) ||
|
||||
(startEnum in ["Sunrise", "Sunset"] && endTime) ||
|
||||
(startEnum in ["Sunrise", "Sunset"] && endEnum in ["Sunrise", "Sunset"])) {
|
||||
def currentTime = now()
|
||||
def start = null
|
||||
def stop = null
|
||||
def sun = getSunriseAndSunset(zipCode: zipCode, sunriseOffset: startSunriseOffset, sunsetOffset: startSunsetOffset)
|
||||
|
||||
if (startEnum == "Sunrise")
|
||||
start = sun.sunrise.time
|
||||
else if (startEnum == "Sunset")
|
||||
start = sun.sunset.time
|
||||
else if (startTime)
|
||||
start = timeToday(startTime,location.timeZone).time
|
||||
|
||||
sun = getSunriseAndSunset(zipCode: zipCode, sunriseOffset: endSunriseOffset, sunsetOffset: endSunsetOffset)
|
||||
if (endEnum == "Sunrise")
|
||||
stop = sun.sunrise.time
|
||||
else if (endEnum == "Sunset")
|
||||
stop = sun.sunset.time
|
||||
else if (endTime)
|
||||
stop = timeToday(endTime,location.timeZone).time
|
||||
|
||||
result = start < stop ? currentTime >= start && currentTime <= stop : currentTime <= stop || currentTime >= start
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private hideOptionsSection() {
|
||||
(startTime || endTime || startEnum || endEnum) ? false : true
|
||||
}
|
||||
|
||||
private offset(value) {
|
||||
def result = value ? ((value > 0 ? "+" : "") + value + " min") : ""
|
||||
}
|
||||
|
||||
private hhmm(time, fmt = "h:mm a") {
|
||||
def t = timeToday(time, location.timeZone)
|
||||
def f = new java.text.SimpleDateFormat(fmt)
|
||||
f.setTimeZone(location.timeZone ?: timeZone(time))
|
||||
f.format(t)
|
||||
}
|
||||
|
||||
private timeIntervalLabel() {
|
||||
def result = ""
|
||||
if (startEnum == "Sunrise" && endEnum == "Sunrise") result = "Sunrise" + offset(startSunriseOffset) + " to " + "Sunrise" + offset(endSunriseOffset)
|
||||
else if (startEnum == "Sunrise" && endEnum == "Sunset") result = "Sunrise" + offset(startSunriseOffset) + " to " + "Sunset" + offset(endSunsetOffset)
|
||||
else if (startEnum == "Sunset" && endEnum == "Sunrise") result = "Sunset" + offset(startSunsetOffset) + " to " + "Sunrise" + offset(endSunriseOffset)
|
||||
else if (startEnum == "Sunset" && endEnum == "Sunset") result = "Sunset" + offset(startSunsetOffset) + " to " + "Sunset" + offset(endSunsetOffset)
|
||||
else if (startEnum == "Sunrise" && endTime) result = "Sunrise" + offset(startSunriseOffset) + " to " + hhmm(endTime, "h:mm a z")
|
||||
else if (startEnum == "Sunset" && endTime) result = "Sunset" + offset(startSunsetOffset) + " to " + hhmm(endTime, "h:mm a z")
|
||||
else if (startTime && endEnum == "Sunrise") result = hhmm(startTime) + " to " + "Sunrise" + offset(endSunriseOffset)
|
||||
else if (startTime && endEnum == "Sunset") result = hhmm(startTime) + " to " + "Sunset" + offset(endSunsetOffset)
|
||||
else if (startTime && endTime) result = hhmm(startTime) + " to " + hhmm(endTime, "h:mm a z")
|
||||
}
|
||||
Reference in New Issue
Block a user