Dim without changing device state (unlinking setLevel from switch state)

One thing that has always driven me a bit nuts about SmartThings is that issuing a setLevel() potentially results in the device changing state from off to on (or vice versa).

I decided to hack around a bit tonight to see what could be done to address this using a Hue bulb as the test device type. Has anyone experimented with this before? I’ve included an excerpt from the device type if anyone is curious. This is mostly throwaway code, but it proves that what I am seeking to do can be accomplished. Any thoughts?

Hue Device Type Excerpt

def on() {
    if(state.requestedLevel != null) {
        onSetLevel(state.requestedLevel)
    } else {
        log.trace parent.on(this)
    }
    sendEvent(name: "switch", value: "on")
}

def setLevel(percent) {

    log.debug "current switch value: ${device.currentValue('switch')}"
    log.debug "latest switch value: ${device.latestValue('switch')}"
    
    if(device.currentValue('switch') == "on")
    {
        if(percent == 0)
        {
            log.debug "Enforcing min setLevel of 1"
            percent = 1
        }

        log.debug "setLevel: ${percent}"
        parent.setLevel(this, percent)
        sendEvent(name: "level", value: percent)
    } else {
        log.debug "Bulb is off, storing requested setLevel: ${percent} for later."
        state.requestedLevel = percent
    }
}

def onSetLevel(percent) {
    log.debug "setLevel: ${percent}"
    parent.setLevel(this, percent)
    sendEvent(name: "level", value: percent)
}
2 Likes

To what extent is this a hardware (firmware) problem specific to each vendor / model?

It’s quite conceivable that many dimmable switched are not designed to accept a setLevel command when (or while staying) turned off, no?

trying desperately to understand the use case for this…

I’d love for Dim/Color/Color temperature changes to not affect On/Off as well. This would make it so much easier to use colors for notifications and adjust color temperature for time of day. The only argument I’ve heard against it is that some physical devices don’t support working this way; apparently the bulbs themselves turn on when sent a new level or color. I would think the device type could simply store the change, and apply it the next time it is send an On command?

2 Likes

This is correct. It is built into the zigbee specs that almost all smart bulbs use (Hue, Cree, GE, Osram) that the level and on/off are interconnected in specific ways. For the level commands most often implemented this involves turning ‘on’ when the level > min (usually 0) and turning ‘off’ when the level <= min. There are alternative level commands that don’t affect the on/off state that we could add to device types for bulbs directly connected to ST, but it might be confusing to the user. Maybe having them not shown in the device tile in the app, and only managed by SmartApps is an option.

Color/Color Temperature would be different. There is no specified connection between the Color Cluster and on/off or level, so each bulb may act differently when sent these commands and there is no alternative command set. Most I’ve seen/tested will turn on when sent any color change command, so this is a hardware issue.

Added: I should note that the example in the original post is the ST -> Hue bridge integration, so ST is at the mercy of how Hue has implemented Level and Color commands to the bulbs. It might be the case that the easiest way to have a consistent user experience is to make sure all “dimmable” devices turn on when issued a level command above 0, which they all work this way.

1 Like

For lights that aren’t automated using motion, open/close sensors, etc, it is difficult to have them change their dim level based on time of day. You either use a time trigger to change their level, in which case if the light was off, it is now on; and you need to turn it back off. Or you have the app subscribe to the ‘on’ event and change the level, but you will still have the light come on bright before changing. I remember someone had an app that did this by changing the level, then immediately turning the light off.

The same issue exists with the Circadian app mentioned, that it must use an automated trigger to dynamically check the time and adjust color/color temp as part of the on() command.

Ah, yea, it would be nice if dimmers supported setDefaultDimLevel or presetDimLevel or the like, so when they do get the on command they immediately go to that level. Every dimmer I’ve worked with (admittedly it’s not that many) does not have this capability built into the hardware. They remember the last dim level they were set to and use that.
So you have two choices that can be implemented universally:
Preset the level by setlevel, then off ahead of time, or set the level when the dimmer is turned on…
And those are the two ways the various apps that attempt to do this sort of thing work.
@bravenel’s app (i believe) pre-stages the dimmers level to the next expected setting requirement (setLevel, then off), and mine triggers from the device on event and sets the levels based on current LUX readings, (on then setLevel)

Zigbee actually has this as part of the spec too. It’s the OnLevel attribute, but it’s Optional and sadly, not all bulbs implement the Optional stuff (most don’t seem to implement anything more than the bare minimum).

In general, I’ve been really impressed with the zigbee specs. Most of the perceived issues are often with the hardware/software implementation, not with holes in the core zigbee functionality. This makes it all the more interesting/fun to try and expand the devicetypes.

Actually, what I’m doing is for dimmers turned on by motion, I just use setLevel to turn them on to the right level. For dimmers controlled by a switch, I use a custom device type that has a command, resetLevel, that sets the level then turns it off. That is only done when the light is off at mode change, or the next time the light is turned off.

1 Like

The way I’ve implemented this allows it to function independent of the capabilities of the device itself. Rather than actually setting the level when a setLevel() is received and the bulb is off, I’m simply storing that value for the next time on() is called. As long as setLevel() works, this approach should work.

Being able to set the ‘default’ dimmer level without actually turning a bulb makes the entire system much more flexible. As an example, when I start watching a movie on the projector, I want to configure the brightness for the hall and kitchen lights such that they do not interrupt the movie when motion is detected. Another added benefit is that bulbs won’t come on full brightness and then fade down to the desired level, they go directly to the desired level. [quote=“bazfum, post:4, topic:28531”]
The only argument I’ve heard against it is that some physical devices don’t support working this way; apparently the bulbs themselves turn on when sent a new level or color
[/quote]
The good news is that we can at least partially work around the issue with the approach I’ve outlined. I’ll plan on putting together a complete device type for the hue bulbs that others can use as an example.

1 Like

I get it now, I didn’t follow the initial description.

I’m pretty sure that the dimmer is still going to ramp from the previous stored level (in the hardware) to the new one, whether cached in the st device state or not. Even if you dink with the ramp rate, you’re still going to see a transition of some sort.

As @Mike_Maxwell observes, this won’t help with the device physical memory of its dimLevel. Furthermore, you don’t even need this if you are using setLevel to turn on the light, because it’s going to come on to the setLevel level with the standard device type. The issue remains of what happens when you turn on the physical switch. My custom device type, Dimmer Switch with Reset, handles changing the physical setting of the switch. It does this by sending a setLevel command, which turns on the switch, and then sending an off command almost instantly after that. You will see the lights flicker on when this happens if you are paying attention.

1 Like

[quote=“bravenel, post:13, topic:28531”]
As @Mike_Maxwell observes, this won’t help with the device physical memory of its dimLevel. Furthermore, you don’t even need this if you are using setLevel to turn on the light, because it’s going to come on to the setLevel level with the standard device type. [/quote]
I’ve not encountered this happening, at least with the hue + hue hub I’m testing with.

As a test case, I can have a hue that is on full bright, turn it off, set the brightness to the minimum and then power it back on – it will power up at minimum brightness just as expected. I have limited experience with devices connected directly to the SmartThings hub, so that very likely could be different.

I think both Mike and I are referring to dimmers, not Hue’s.

1 Like

I probably use SmartThings a bit differently than many people do. I don’t have any physical dimmers, partly because I live in an apartment, but also because I want things to be as automated as possible. I primarily rely on motion sensors to turn lights on/off.

That’s interesting. The house I bought came with a zillion dimmers, so I had to do something with them! My office has 4, my bedroom has 8. Good grief, it’s ridiculous! So, like you, almost all of my dimmers are turned on/off by motion. But, I do have physical dimmers.

For anyone still following along, here’s the device type I’m currently using for my Hue bulbs:

This is based on @zpriddy’s device types and implements the Hue transition time as well as groups. You can see more here.

1 Like

This looks amazing! I am planning on doing some more cleanup soon and I think I might build off of this! Thank you! :slight_smile:

1 Like

Encountered a bit of a setback tonight. It seems that my Harmony remotes only send setLevel(...) when turning a dimable light on. That means with my device types there is no way to turn on a light with a harmony remote.

It seems that I will need to take another path to accomplishing my end goal in order to maintain compatibility with things like Harmony. I’m leaning towards adding a setDefaultLevel(...) method which the slider in the ST app will call. This allows me to accomplish my goal of improving the user experience in the ST app without creating compatibility issues.