Virtual Switch/Bulb with Dimming and Color (Virtual Hue Bulb)

Before I venture down trying to create this Virtual device type my self I was wondering if anyone has already created a Virtual Switch/Bulb with Dimming and Color (Virtual Hue Bulb) capabilities. I have some use cases that would be nice to leverage a single virtual switch to change color and dim multiple dimmable and color enable bulbs at the same time. There are other ways I could do this but i’d like to attempt a virtual dimmable and color enable bulb.

Even with a virtual color changing dimmer, aren’t you gonna need a smartapp as well to keep the physical switches in sync with the virtual one?

1 Like

Yes, these already exist.

I would use “Dim with Me” a community app by @twack that lets me turn on a set of lights and dim then based on the settings of the master switch.

For color I would use “Color Coordinator” which sets color based on a master switch/light.

I could probably write a new smart app and merge the code for these two to make a single app.

1 Like

I did this for the Fibaro RGBW controller, but I don’t know that it’ll translate to any color bulb, especially all the extra presets that twack created.

Here’s the virtual device and the SmartApp is in the same repo.

True: And this is an unfortunate fact of the SmartThings platform; i.e., Device Handlers are not permitted to directly control devices other than itself.

Various good reasons for this, but it does make Virtual Device development more convoluted than preferred.

@Sticks18 Thanks for the code, I merged/modified it with the ST Hue Bulb code so I got it to work and look like the Hue Bulb. Mainly copy pasted the functions and seems to work, didn’t have time to actually examine the code but using my code I have a Virtual Hue Bulb that has the new Hue Bulb layout in ST. It turns on/off, dims and changes colour. I’m noticing in the activity log that it’s not capturing color changes but it is changing. I’ll go through the code line by line when I have the time.

I just stripped out the zwave stuff from @twack’s great device type to create the virtual shell.

Looks like the color events have the ‘displayed: false’ option, probably to minimize activity that won’t mean much to most users hue/saturation/level combos and instead only sends the events for preset colors. You should be able to remove that from the various sendEvent commands (lines 239, 309-311, 590).

i’d love to make a virtual switch with dimming/color support, so i could put all my hue bulbs under it. does anyone have code that would work? i guess i would need a proper device type?

Hello, this code looks promising for my use. However, it would be very helpful if it could include an effectivity time option, i.e. only perform the follow me dimming during times of the day from sunset to sunrise. I have an exterior surveillance system that can send an email when it detects motion. Using IFTTT connected to the surveillance email as a trigger, I can set a virtual switch in ST to maintain the motion sensed condition. Then this follow me code would turn on outside lights. It would be helpful to limit these lights to turn on only when dark.

Any help would be appreciated. I’m not familiar with coding this type of functionality.

Thanks in advance.

@huydnguyen - I am searching for a virtual device that allows me to change color, dim up and down and turn on/off. I would sync settings made to this virtual device to a number of other lights using webcore rather than stand alone smart apps.

Have you ever finished the virtual device? Could you share it? Do you know whether it can be used with webCore?

1 Like

This should work for you. You could use WebCore to control the dimmer. It will expose color, level and switch. It also adds an extra disable/enable command so you could disable or enable the dimmer based upon rules or by hand.
/**

  • Virtual Dimmer
  • Copyright 2017 Jason Zheng
  • Version 1.0.0 11/04/17
  • Version 1.0.0 - Based upon Michael Struck’s Virtual Color Temp V2. Add a
  • Uses code from SmartThings
  • 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: "Virtual Dimmer", namespace: "jasonz2k", author: "Jason Zheng") {

	capability "Actuator"
	capability "Refresh"
	capability "Switch"
	capability "Switch Level"
	capability "Color Temperature"

    
    	attribute "bulbTemp", "string"
        attribute "disable", "string"
        command "todisable"
        command "toenable"
        command "toggleEnable"
        command "tuneup"
        command "tunedown"
    
}


// UI tile definitions
tiles {
	standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
		state "off", label: '${name}', action: "switch.on", icon: "st.switches.light.off", backgroundColor: "#ffffff"
		state "on", label: '${name}', action: "switch.off", icon: "st.switches.light.on", backgroundColor: "#79b821"
	}
	standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") {
		state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
	}
	controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 2, inactiveLabel: false) {
		state "level", action:"switch level.setLevel"
	}
    controlTile("colorSliderControl", "device.colorTemperature", "slider", height: 1, width: 2, inactiveLabel: false, range: "(2700..6500)") {
		state "colorTemperature", action:"color temperature.setColorTemperature"
	}
	valueTile("kelvin", "device.colorTemperature") {
		state "colorTemperature", label:'${currentValue}k',
			backgroundColors:[
				[value: 2900, color: "#FFA757"],
				[value: 3300, color: "#FFB371"],
				[value: 3700, color: "#FFC392"],
				[value: 4100, color: "#FFCEA6"],
				[value: 4500, color: "#FFD7B7"],
				[value: 4900, color: "#FFE0C7"],
				[value: 5300, color: "#FFE8D5"],
                [value: 6600, color: "#FFEFE1"]
			]
	}
    valueTile("bulbTemp", "device.bulbTemp", inactiveLabel: false, decoration: "flat") {
		state "bulbTemp", label: '${currentValue}'
	}
    valueTile("level", "device.level", inactiveLabel: false, decoration: "flat") {
		state "level", label: 'Level ${currentValue}%'
	}
	
	standardTile("disable", "device.disable", width: 1, height: 1, canChangeIcon: true) {
		state "off", label: 'enabled', action: "todisable", icon: "st.switches.light.on", backgroundColor: "#79b821"
		state "on", label: 'disabled', action: "toenable", icon: "st.switches.light.off", backgroundColor: "#ff0000"
	}
	main(["switch"])
	details(["switch", "bulbTemp", "refresh", "levelSliderControl", "level", "colorSliderControl", "kelvin", "disable"])
}

def parse(String description) {
}

def on() {
if(state.switchDisable )
return;
sendEvent(name: “switch”, value: “on”)
//sendEvent(name: “level”,value: device.currentValue(“level”))
//sendEvent(name: “switch.setLevel”, value: device.currentValue(“level”))
// setLevel(device.currentValue(“level”))
//sendEvent(name: “switch”, value:“on”)
//log.info "set level ${device.currentValue(“level”)}"
log.info “Dimmer On”
}

def off() {
if(state.switchDisable )
return;
sendEvent(name: “switch”, value: “off”)
log.info “Dimmer Off”
}

def todisable() {
state.switchDisable = true
sendEvent(name: “disable”, value: “on”)
log.info “Dimmer disabled”
}

def toenable() {
state.switchDisable = false;
sendEvent(name: “disable”, value: “off”)
log.info “Dimmer enabled”
}

def toggleEnable() {
if(state.switchDisable){
toenable()
}else{
todisable()
}
}

def tuneup(){
def level = device.currentValue(“level”)
log.info(“switchLevel: $level”)
if(level < 100){
setLevel(level+20)
}
}

def tunedown(){
def level = device.currentValue(“level”)
log.info(“switchLevel: $level”)
if(level >20){
setLevel(level-20)
}
}

def setLevel(val){

if(state.switchDisable )
   return
log.info "setLevel $val"

// make sure we don't drive switches past allowed values (command will hang device waiting for it to
// execute. Never commes back)
if (val < 0){
	val = 0
}

if( val > 100){
	val = 100
}

if (val == 0){ 
	sendEvent(name:"level",value:val)
	off()
}
else
{
	on()
	sendEvent(name:"level",value:val)
	sendEvent(name:"switch.setLevel",value:val)
}

}

def refresh() {
log.info “refresh”
}

def setColorTemperature(value) {

log.trace "setColorTemperature($value)"

def degrees = Math.max(2700, value)
if(value > 2700){
	degrees = Math.min(6500, value)
}
def bTemp = getBulbTemp(value)

log.trace degrees

sendEvent(name: "colorTemperature", value: degrees)
sendEvent( name: "bulbTemp", value: bTemp)

}

private getBulbTemp(value) {

def s = "Soft White"

if (value < 2900) {
	return s
} 
else if (value < 3350) {
	s = "Warm White"
    return s
}
else if (value < 3900) {
	s = "Cool White"
    return s
}
else if (value < 4800) {
	s = "Bright White"
    return s
}
else if (value < 5800) {
	s = "Natural"
    return s
}
else {
	s = "Daylight"
    return s
}

}

2 Likes

Here’s a WebCore piston to integrate this virtual dimmer with Minimote.

I’m getting “Org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: script_dth_metadata_3363ec80_0af2_4d42_9ca7_f6720a490cc3: 84: Invalid variable name. Must start with a letter but was: “switch” . At [84:17] @ line 84, column 17. sendEvent(name: “switch”, value: “on”) ^ 1 error” when I try to copy and paste this code into New Device Handler in IDE. Any idea what I’m doing wrong?

The quotes in the post need to be replaced from “ and ” to "

Smartthings doesn’t really like directional quotes, and there are a few. You can replace them yourself, because I tried uploading the corrected version about 4 times and it appears that they’ll convert themselves back to directional quotes.

So, I’ve got this to work for the most part, but the color temp slider isn’t limited as it should be. It looks right in the code, but the range in app is 0 to 100k. Is mirroring in Smart Lighting the wrong thing to do? Any thoughts?