Store previous Hue color values

I’m not a programmer, but I do generally have the ability to customize and combine existing code to do what I want with it. However, I’m pretty stumped on this one. I’m using something mostly based on SmartThings’ Hue Mood Lighting and Dan999’s power monitoring code here: Say goodnight when you turn off your night stand light

I have a SmartThings Outlet which my projector is plugged into. I want to monitor that outlet, and when it detects that I have turned on the projector, I want my Hue bulbs to dim to a 1% purple. When I turn the projector off, I want the lights to go back to whatever their previous state was.

It’s that last part that I’m having trouble with. No matter what I try, I can’t seem to figure out a way to save the previous values in order to go back to them later. I’m sure I’m missing something stupid, but if anyone can help out with this it’d be appreciated. Here’s what I’ve got - currently have it hardcoded to return to a daylight color at 100% brightness after the projector turns off, since I can’t figure out anything else.

definition(
    name: "Theatre Mode",
    namespace: "jhoff80",
    author: "jhoff80",
    description: "When the projector is on, change the Hue colors.  Code based on SmartThings' Hue Mood Lighting and dpvorster's Good Night.",
    category: "Convenience",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/hue.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/hue@2x.png"
)

preferences 
{
    page(name: "settings", title: "Settings")
}

def settings() 
{
    dynamicPage(name: "settings", install: true, uninstall: true) 
    {		
        section("Outlet to Monitor") {
            input "switch1", "capability.powerMeter", title: "Where?"
        }
        section("Wattage for On State") {
        	input "wattage", "number", title: "Power Draw", required: true, defaultValue: '50'
            }
		section("Control these bulbs...") {
			input "hues", "capability.colorControl", title: "Which Hue Bulbs?", required:true, multiple:true
		}
		section("Choose light effects...")
			{
				input "color", "enum", title: "Hue Color?", required: false, multiple:false, options: [
					"Daylight","Warm White","Red","Green","Blue","Yellow","Orange","Purple","Pink"]
				input "lightLevel", "number", title: "Light Level?", required: false
			}
        section ("") {
            label title: "Assign a name", required: false
            input "modes", "mode", title: "Set for specific mode(s)", multiple: true, required: false
        }
    }
} 

def installed() 
{
	initialize()
}

def updated() 
{
	initialize()
}

def initialize()
{   
	unsubscribe()
	subscribe (switch1, "power", eventHandler)
    log.debug "Subscribed to power event for $switch1"
}

def eventHandler(evt)
{   
	log.debug "eventHandler, wasOn=$state.wasOn"
    if (! state.wasOn) 
    {
    	state.wasOn = (switch1.currentValue('power') > wattage)
    }
    if ( state.wasOn)
    {
			takeActions()
		}
}

private takeActions(evt) 
{
if (isPowerOn())
        {
	def hueColor = 0
	def saturation = 100

	switch(color) {
		case "Daylight":
			hueColor = 53
			saturation = 91
			break;
		case "Warm White":
			hueColor = 20
			saturation = 80
			break;
		case "Blue":
			hueColor = 70
			break;
		case "Green":
			hueColor = 39
			break;
		case "Yellow":
			hueColor = 25
			break;
		case "Orange":
			hueColor = 10
			break;
		case "Purple":
			hueColor = 75
			break;
		case "Pink":
			hueColor = 83
			break;
		case "Red":
			hueColor = 100
			break;
	}

	state.previous = [:]

	hues.each {
		state.previous[it.id] = [
			"switch": it.currentValue("switch"),
			"level" : it.currentValue("level"),
            "hue": it.currentValue("hue"),
			"saturation": it.currentValue("saturation")
		]
	}
	log.debug "current values = $state.previous"
    def newValue = [hue: hueColor, saturation: saturation, level: lightLevel as Integer ?: 100]
	log.debug "new value = $newValue"

	hues*.setColor(newValue)
     }
if (! isPowerOn())
        {
   	def hueColor = 53
    def saturation = 91
    def lightLevel = 100
    
    state.previous = [:]

	hues.each {
		state.previous[it.id] = [
			"switch": it.currentValue("switch"),
			"level" : it.currentValue("level"),
			"hue": it.currentValue("hue"),
			"saturation": it.currentValue("saturation")
		]
	}
	log.debug "current values = $state.previous"

	def newValue = [hue: hueColor, saturation: saturation, level: lightLevel as Integer ?: 100]
	log.debug "new value = $newValue"

	hues*.setColor(newValue) 
     }
     state.wasOn=false;
}

private isPowerOn(evt) 
{
	def power = switch1.currentValue('power')
	log.debug "Power is $power"
	power > wattage
}

It looks like you’re on the right track here. In the if (isPowerOn()) section, you’ve saved the state of the bulbs in state.prevous. In if (! isPowerOn()), you should use those saved values. something like this:

if (! isPowerOn()) {
  hues.each {
    it.setColor(state.previous[it.id])
  }
}
1 Like

So it’s looking like I’m running into an issue with it running through the “PowerOn” section repeatedly while the projector power is triggered, so even if it stores the state after the first iteration of the event handler, when it then runs through a second iteration the new state overwrites that.

I could probably figure out another if/then statement but for now I’m just going to stick to the hard-coded values because that’s working ‘good enough’ for me at this point.

I suspect the app is running for each hue since they will all fire events. I use the following in one of my apps and maybe it will work for you:
def deviceName = evt.name
state."${deviceName}Warm" = now()

So you can set a state variable like state."${deviceName}Level" = it.currentValue(“level”)

You should request @pstuart to have this as a Friday live coding topic.

I wanted to try a new way of approaching this so I instead took a look at the SmartThings “Energy Alerts” code and attempted to customize from there. This gave me something that seems far cleaner… but the same issue is happening. Based on the logs, I see the “dimming” happening 3-4 times in a row, despite the way that this now is checking to make sure the last value was below the threshold before triggering. I’m assuming this means the meter might actually be updating too fast, but I’m not really sure.

In short, I give up. :smiley:

[code]definition(
name: “Theatre Mode”,
namespace: “jhoff80”,
author: “jhoff80”,
description: “When the projector is on, change the Hue colors. Code based on SmartThings’ Hue Mood Lighting and Energy Alerts.”,
category: “Convenience”,
iconUrl: “https://s3.amazonaws.com/smartapp-icons/Partner/hue.png”,
iconX2Url: “https://s3.amazonaws.com/smartapp-icons/Partner/hue@2x.png”)

preferences {
section {
input(name: “meter”, type: “capability.powerMeter”, title: “When This Power Meter…”, required: true, multiple: false, description: null)
input(name: “aboveThreshold”, type: “number”, title: “Reports Above…”, required: true, description: “in either watts or kw.”)
input “hues”, “capability.colorControl”, title: “Which Hue Bulbs?”, required: true, multiple: true
input “color”, “enum”, title: “Hue Color?”, required: false, multiple: false, options: [“Daylight”, “Warm White”, “Red”, “Green”, “Blue”, “Yellow”, “Orange”, “Purple”, “Pink”]
input “lightLevel”, “number”, title: “Light Level?”, required: false
}
}

def installed() {
initialize()
}

def updated() {
unsubscribe()
initialize()
}

def initialize() {
subscribe(meter, “power”, meterHandler)
}

def meterHandler(evt) {
def meterValue = evt.value as double
if (!atomicState.lastValue) {
atomicState.lastValue = meterValue
}
def lastValue = atomicState.lastValue as double
atomicState.lastValue = meterValue
def aboveThresholdValue = aboveThreshold as int
if (meterValue > aboveThresholdValue) {
if (lastValue < aboveThresholdValue) {
log.debug "Dimming"
takeActions(evt)
}
}
if (meterValue < aboveThresholdValue) {
if (lastValue > aboveThresholdValue) {
log.debug "Brightening"
takeAction(evt)
}
}
}

private takeActions(evt) {
def hueColor = 0
def saturation = 100
switch (color) {
case “Daylight”:
hueColor = 53
saturation = 91
break;
case “Warm White”:
hueColor = 20
saturation = 80
break;
case “Blue”:
hueColor = 70
break;
case “Green”:
hueColor = 39
break;
case “Yellow”:
hueColor = 25
break;
case “Orange”:
hueColor = 10
break;
case “Purple”:
hueColor = 75
break;
case “Pink”:
hueColor = 83
break;
case “Red”:
hueColor = 100
break;
}
state.previous = [:]
hues.each {
state.previous[it.id] = [
“switch”: it.currentValue(“switch”),
“level” : it.currentValue(“level”),
“hue”: it.currentValue(“hue”),
“saturation”: it.currentValue(“saturation”)
]
}
log.debug "current values = $state.previous"
def newValue = [hue: hueColor, saturation: saturation, level: lightLevel as Integer ?: 100]
log.debug "new value = $newValue"
hues*.setColor(newValue)
}

private takeAction(evt) {
hues.each {
it.setColor(state.previous[it.id])
}
}[/code]