-
Official SmartThings tech support.
-
“Solution” SmartApps (aka Dashboard SmartApps?)… Also officially supported by SmartThings Tech Support.
Most importantly - not needing to rewrite bulk of ST functionality from scratch. But if it is not possible to do via code, it is kind of moot.
Hey, i now know what they are called!!
so close…
-M
So what is the answer here? I have a hallway light that I only want to come on in the dark. If the light is already on I don’t want it to run.
There may be a better way these days, but back then I ended up writing a custom app that created two virtual switches - one for motion sensor to control and one for override. The real switch would be on if EITHER of the switches is on, and off when both are off. This way I control it via the override switch if I want it to stay on (normal operation) and while motion sensor controls a switch like normal, it only turns on/off the light if it was not on already.
I must be dumb. I can’t find a smartapp for this. Any tips were I should look for smartapps?
Not dumb, I could not find one either, so I wrote one .
Just checked, and it looks like I also wrote a different version that only creates one virtual switch that remembers if it was used to turn the device on when turning it off - so that you can control it normally but add the motion to the virtual switch.
I just published them to my github, if you want to try them out - mlasevich/SmartThingsMirrorSwitch/master
-M
thanks!!!
“physicalgraph.app.exception.UnknownDeviceTypeException: Device type ‘On/Off Button Tile’ in namespace ‘smartthings’ not found. @ line 59”
The switch is a dimmer, would that cause a problem?
Heh, looks like I forgot something. Its been a while since I did this and I did not intend this for a wider audience… but from what I see, it is expecting a device handler called “On/Off Button Tile” - which is published by SmartThings
There is probably a better way to add it from SmartThings, but here is the definition to add it manually:
/**
* On/Off Button Tile
*
* Author: SmartThings
*
* Date: 2013-05-01
*/
metadata {
// Automatically generated. Make future change here.
definition (name: "On/Off Button Tile", namespace: "smartthings", author: "SmartThings") {
capability "Actuator"
capability "Switch"
capability "Sensor"
}
// simulator metadata
simulator {
}
// UI tile definitions
tiles {
standardTile("button", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "off", label: 'Off', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "on"
state "on", label: 'On', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821", nextState: "off"
}
main "button"
details "button"
}
}
def parse(String description) {
}
def on() {
sendEvent(name: "switch", value: "on")
}
def off() {
sendEvent(name: "switch", value: "off")
}
Let me know how it works out
Oh, there it is - you can create it by creating a new device handler, and choosing “From Template” and choosing “On/Off Tile” from the list. Don’t forget to publish
Use my app…
/**
- Smart Timer
- Loosely based on “Light Follows Me”
- This prevent them from turning off when the timer expires, if they were already turned on
- If the switch is already on, if won’t be affected by the timer (Must be turned of manually)
- If the switch is toggled while in timeout-mode, it will remain on and ignore the timer (Must be turned of manually)
- The timeout perid begins when the contact is closed, or motion stops, so leaving a door open won’t start the timer until it’s closed.
- Author: andersheie@gmail.com
- Date: 2015-10-30
*/definition(
name: “Smart Light Timer, X minutes unless already on”,
namespace: “Pope”,
author: “listpope@cox.net”,
description: “Turns on a switch for X minutes, then turns it off. Unless, the switch is already on, in which case it stays on. If the switch is toggled while the timer is running, the timer is canceled.”,
category: “Convenience”,
iconUrl: “http://upload.wikimedia.org/wikipedia/commons/6/6a/Light_bulb_icon_tips.svg”,
iconX2Url: “http://upload.wikimedia.org/wikipedia/commons/6/6a/Light_bulb_icon_tips.svg”)preferences {
section(“Turn on when there is movement…”){
input “motions”, “capability.motionSensor”, multiple: true, title: “Select motion detectors”, required: false
}
section(“Or, turn on when one of these contacts opened”){
input “contacts”, “capability.contactSensor”, multiple: true, title: “Select Contacts”, required: false
}
section(“Or, turn on when any of these people come home”) {
input “peoplearrive”, “capability.presenceSensor”, multiple: true, required: false
}
section(“Or, turn on when any of these people leave”) {
input “peopleleave”, “capability.presenceSensor”, multiple: true, required: false
}
section(“And off after no more triggers after…”){
input “minutes1”, “number”, title: “Minutes?”, defaultValue: “5”
}
section(“Turn on/off light(s)…”){
input “switches”, “capability.switch”, multiple: true, title: “Select Lights”
}
}def installed()
{
log.debug “installed()”
initialize()
}def updated()
{
log.debug “updated()”
initialize()
}def initialize()
{
log.debug “initialize()”
// Reset to new set of Switches, just in case.
unsubscribe()state.switches = [:] switches.each { // log.debug "ID: $it.id" // Set ready state for each switch state.switches["$it.id"] = "ready" } logStates()
subscribe(motions, “motion”, motionHandler)
subscribe(switches, “switch”, switchChange)
subscribe(contacts, “contact”, contactHandler)
subscribe(peoplearrive, “presence.present”, presencePresentHandler)
subscribe(peopleleave, “presence.not present”, presenceNotPresentHandler)
state.lastAction = null
schedule(“0 * * * * ?”, “scheduleCheck”)}
def logStates() {
if(state.switches == null) {
state.switches = [:]
}
state.switches.each {
log.debug “State: $it.key = $it.value”
}
}def turnSwitchOn(id) {
for(S in switches) {
if(S.id == id) {
S.on()
}
}
}def turnSwitchOff(id) {
for(S in switches) {
if(S.id == id) {
S.off()
}
}
}def initState(deviceID) {
// Have to add this so existing apps that are neither updated nor initiated can slowly get ‘reset’ with states.
// Smartthings doesn’t call any specific method when new version is published.if(state.switches == null) {
state.switches = [:]
}
if(state.switches[deviceID] == null) {
state.switches[deviceID] = “ready”
}}
def switchChange(evt) {
def deviceID = evt.device.id
log.debug "SwitchChange: $evt.name: $evt.value $evt.device.id current state = " + state.switches[deviceID]
initState(deviceID)if(evt.value == “on”) {
if(state.switches[deviceID] == “activating”) {
// OK, probably an event from Activating something, and not the switch itself. Go to Active mode.
log.debug “$deviceID = " + state.switches[deviceID] + " → active”
state.switches[deviceID] = “active”
} else if(state.switches[deviceID] != “active”) {
log.debug “$deviceID = " + state.switches[deviceID] + " → already on”
state.switches[deviceID] = “already on”
}
} else {
// If active and switch is turned of manually, then stop the schedule and go to ready state
state.switches[deviceID] = “ready”
}
logStates()}
def contactHandler(evt) {
log.debug “contactHandler: $evt.name: $evt.value”state.switches.each { thisswitch -> initState(thisswitch.key) //log.debug "Looking for $thisswitch.key" if (evt.value == "open") { if(state.switches[thisswitch.key] == "ready") { log.debug "Turning on lights by contact opening: $thisswitch" log.debug "$thisswitch.key = " + state.switches[thisswitch.key] + " -> activating" state.switches[thisswitch.key] = "activating" turnSwitchOn(thisswitch.key) setActiveAndSchedule() } } else if (evt.value == "closed") { if (!state.lastAction && (state.switches[thisswitch.key] == "active" || state.switches[thisswitch.key] == "activating")) { // When contact closes, we reset the timer if not already set log.debug "$thisswitch.key = " + state.switches[thisswitch.key] + " -> active" state.switches[thisswitch.key] = "active" setActiveAndSchedule() } } } logStates()
}
def scheduleCheck() {
log.debug “schedule check, ts = ${state.lastAction}”
boolean resetInactive = false
state.switches.each { thisswitch →
initState(thisswitch.key)
if(state.switches[thisswitch.key] != “already on”) {
if(state.lastAction != null) {
def elapsed = now() - state.lastAction
log.debug “${elapsed / 1000} sec since events stopped”
def threshold = 1000 * 60 * minutes1
if (elapsed >= threshold) {
if (state.switches[thisswitch.key] == “active”
|| state.switches[thisswitch.key] == “activating”) {
state.switches[thisswitch.key] = “ready”
log.debug “Turning off lights by switch closing: $thisswitch”
turnSwitchOff(thisswitch.key)
}
resetInactive = true
}
}
}
}
if(resetInactive) {
state.lastAction = null
unschedule()
}
logStates()
}/**********************************************************************/
def motionHandler(evt) {
log.debug "motionHandler: $evt.name: $evt.value (current state: " + state.myState + “)”state.switches.each { thisswitch →
initState(thisswitch.key)
if (evt.value == “active”) {
if(state.switches[thisswitch.key] == “ready”
|| state.switches[thisswitch.key] == “active”
|| state.switches[thisswitch.key] == “activating” ) {
log.debug “$thisswitch.key = " + state.switches[thisswitch.key] + " → activating”
state.switches[thisswitch.key] = “activating”
turnSwitchOn(thisswitch.key)
setActiveAndSchedule()
}
} else if (evt.value == “inactive”) {
if (state.switches[thisswitch.key] == “active” || state.switches[thisswitch.key] == “activating”) {
// When Motion ends, we reset the timer if not already set
log.debug “$thisswitch.key = " + state.switches[thisswitch.key] + " → active”
state.switches[thisswitch.key] = “active”
setActiveAndSchedule()
}
}
}
logStates()
}def presencePresentHandler(evt) {
log.debug “presence: $evt.linkText is now $evt.value”state.switches.each { thisswitch -> initState(thisswitch.key) if (evt.value == "present") { if(state.switches[thisswitch.key] == "ready" || state.switches[thisswitch.key] == "active" || state.switches[thisswitch.key] == "activating" ) { log.debug "Presence turning on switch $thisswitch" state.switches[thisswitch.key] = "active" turnSwitchOn(thisswitch.key) // We don't wait until the person leave, but instead start timer immediately. setActiveAndSchedule() } } } logStates()
}
def presenceNotPresentHandler(evt) {
log.debug “presence: $evt.linkText is now $evt.value”state.switches.each { thisswitch -> initState(thisswitch.key) if (evt.value == "not present") { if(state.switches[thisswitch.key] == "ready" || state.switches[thisswitch.key] == "active" || state.switches[thisswitch.key] == "activating" ) { log.debug "No Presence turning on lights $thisswitch" state.switches[thisswitch.key] = "active" turnSwitchOn(thisswitch.key) // We don't wait until the person arrive back, but instead start timer immediately. setActiveAndSchedule() } } } logStates()
}
def setActiveAndSchedule() {
unschedule()
state.lastAction = now()
schedule(“0 * * * * ?”, “scheduleCheck”)
log.debug “Scheduled new timer”
}