[RELEASE] Z-Wave Dimmer Switch with stepper and Low/Med/High

Here is the new Z-Wave dimmer switch control I have created. This dimmer switch allows you to use the standard controls as well as the configurable Low/Med/High buttons and stepper to increase or decrease by a selected value. There are still a couple bugs I’m working to resolve but would like to release this, as functionally it is working as expected. Below is a screenshot:

Details:

Preferences:

Here is the code:


/* Dimmer-Switch-Levels.device.groovy
 *
 * Variation of the stock SmartThings "Dimmer-Switch"
 * Variation of the twack "Better-Dimmer-Switch"
 * Variation of the ChadCK "Z-Wave Smart Fan Control"
 *
 * Device type adds set levels low, medium, and High for preset values (Moods).
 * Adds increment up and down buttons with ability to set value.
 *
 * pmjoen@yahoo.com
 * 20160517
 *  
 * v1.0 - Initial release of device handler
 *  
*/

metadata {
	// Automatically generated. Make future change here.
	definition (name: "Dimmer-Switch-Levels", namespace: "pmjoen", author: "SmartThings") {
		capability "Switch Level"
		capability "Actuator"
		capability "Indicator"
		capability "Switch"
		capability "Polling"
		capability "Refresh"
		capability "Sensor"

		command "on"
		command "off"
        command "low"
		command "med"
		command "high"
        command "levelUp"
        command "levelDown"

		attribute "currentState", "string"

		//fingerprint deviceId: "0x1101", inClusters: "0x26, 0x27, 0x70, 0x86, 0x72"
	}

		tiles(scale: 2) {
		multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4
        , canChangeIcon: true){
			tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
				attributeState "default", label:'ADJUSTING', action:"refresh.refresh", icon:"st.Lighting.light24", backgroundColor:"#2179b8", nextState: "turningOff"
				attributeState "HIGH", label:'HIGH', action:"switch.off", icon:"st.Lighting.light24", backgroundColor:"#79b821", nextState: "turningOff"
				attributeState "MED", label:'MED', action:"switch.off", icon:"st.Lighting.light24", backgroundColor:"#79b821", nextState: "turningOff"
				attributeState "LOW", label:'LOW', action:"switch.off", icon:"st.Lighting.light24", backgroundColor:"#79b821", nextState: "turningOff"
				attributeState "off", label:'OFF', action:"switch.on", icon:"st.Lighting.light24", backgroundColor:"#ffffff", nextState: "turningOn"
                attributeState "on", label:'ON', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
				attributeState "turningOn", action:"switch.on", label:'TURNINGON', icon:"st.Lighting.light24", backgroundColor:"#2179b8", nextState: "turningOn"
				attributeState "turningOff", action:"switch.off", label:'TURNINGOFF', icon:"st.Lighting.light24", backgroundColor:"#2179b8", nextState: "turningOff"
			}
            
    	tileAttribute("device.level", key: "VALUE_CONTROL") {
                attributeState("VALUE_UP", action: "levelUp")
                attributeState("VALUE_DOWN", action: "levelDown")
			}
		tileAttribute ("device.level", key: "SLIDER_CONTROL") {
				attributeState "level", action:"switch level.setLevel"
			}
		}

		standardTile("indicator", "device.indicatorStatus", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
			state "when off", action:"indicator.indicatorWhenOn", icon:"st.indicators.lit-when-off"
			state "when on", action:"indicator.indicatorNever", icon:"st.indicators.lit-when-on"
			state "never", action:"indicator.indicatorWhenOff", icon:"st.indicators.never-lit"
		}

		standardTile("refresh", "device.switch", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
			state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
		}

		valueTile("level", "device.level", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
			state "level", label:'${currentValue} %', unit:"%", backgroundColor:"#ffffff"
		}
        
        standardTile("low", "device.currentState", inactiveLabel: false, width: 2, height: 2) {
        	state "default", label: 'LOW', action: "low", icon:"st.Weather.weather4", backgroundColor: "#ffffff"
            state "ADJUSTING.LOW", label:'LOW', action: "low", icon:"st.Weather.weather4", backgroundColor: "#2179b8"
			state "LOW", label:'LOW', action: "low", icon:"st.Weather.weather4", backgroundColor: "#79b821"
  		}
        
		standardTile("med", "device.currentState", inactiveLabel: false, width: 2, height: 2) {
			state "default", label: 'MED', action: "med", icon:"st.illuminance.illuminance.light", backgroundColor: "#ffffff"
            state "ADJUSTING.MED", label:'MED', action: "med", icon:"st.illuminance.illuminance.light", backgroundColor: "#2179b8"
            state "MED", label: 'MED', action: "med", icon:"st.illuminance.illuminance.light", backgroundColor: "#79b821"
		}
            
		standardTile("high", "device.currentState", inactiveLabel: false, width: 2, height: 2) {
			state "default", label: 'HIGH', action: "high", icon:"st.illuminance.illuminance.bright", backgroundColor: "#ffffff"
            state "ADJUSTING.HIGH", label:'HIGH', action: "high", icon:"st.illuminance.illuminance.bright", backgroundColor: "#2179b8"
			state "HIGH", label: 'HIGH', action: "high", icon:"st.illuminance.illuminance.bright", backgroundColor: "#79b821"
		}

		main(["switch"])
        details(["switch", "low", "med", "high", "level", "indicator", "refresh"])
        
	}
    preferences {
		section("Light Level Values") {
			input "lowThreshold", "number", title: "Low Level", range: "1..99"
			input "medThreshold", "number", title: "Medium Level", range: "1..99"
			input "highThreshold", "number", title: "High Level", range: "1..99"
		}
        section ("Interval Selection") {
            input "stepper", "enum", title: "Interval Value", defaultValue: "10", options: ["5","10","20"]
        }
	}
}

def parse(String description) {
	def item1 = [
		canBeCurrentState: false,
		linkText: getLinkText(device),
		isStateChange: false,
		displayed: false,
		descriptionText: description,
		value:  description
	]
	def result
	def cmd = zwave.parse(description, [0x20: 1, 0x26: 1, 0x70: 1])
	if (cmd) {
		result = createEvent(cmd, item1)
	}
	else {
		item1.displayed = displayed(description, item1.isStateChange)
		result = [item1]
	}
	log.debug "Parse returned ${result?.descriptionText}"
	result
}

def createEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd, Map item1) {
	def result = doCreateEvent(cmd, item1)
	for (int i = 0; i < result.size(); i++) {
  	result[i].type = "physical"
	}
	log.trace "BasicReport"
  result
}

def createEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd, Map item1) {
	def result = doCreateEvent(cmd, item1)
	for (int i = 0; i < result.size(); i++) {
		result[i].type = "physical"
	}
	log.trace "BasicSet"
	result
}

def createEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelStartLevelChange cmd, Map item1) {
	[]
	log.trace "StartLevel"
}

def createEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelStopLevelChange cmd, Map item1) {
	[response(zwave.basicV1.basicGet())]
}

def createEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelSet cmd, Map item1) {
	def result = doCreateEvent(cmd, item1)
	for (int i = 0; i < result.size(); i++) {
		result[i].type = "physical"
	}
	log.trace "SwitchMultiLevelSet"
	result
}

def createEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelReport cmd, Map item1) {
	def result = doCreateEvent(cmd, item1)
	result[0].descriptionText = "${item1.linkText} is ${item1.value}"
	result[0].handlerName = cmd.value ? "statusOn" : "statusOff"
	for (int i = 0; i < result.size(); i++) {
		result[i].type = "digital"
	}
	log.trace "SwitchMultilevelReport"
	result
}

def doCreateEvent(physicalgraph.zwave.Command cmd, Map item1) {
	def result = [item1]
	def lowThresholdvalue = (settings.lowThreshold != null && settings.lowThreshold != "") ? settings.lowThreshold.toInteger() : 33
	def medThresholdvalue = (settings.medThreshold != null && settings.medThreshold != "") ? settings.medThreshold.toInteger() : 67
	def highThresholdvalue = (settings.highThreshold != null && settings.highThreshold != "") ? settings.highThreshold.toInteger() : 99

	item1.name = "switch"
	item1.value = cmd.value ? "on" : "off"
	if (item1.value == "off") {
		sendEvent(name: "currentState", value: "off" as String)
	}
	item1.handlerName = item1.value
	item1.descriptionText = "${item1.linkText} was turned ${item1.value}"
	item1.canBeCurrentState = true
	item1.isStateChange = isStateChange(device, item1.name, item1.value)
	item1.displayed = false

	if (cmd.value) {
		def item2 = new LinkedHashMap(item1)
		item2.name = "level"
		item2.value = cmd.value as String
		item2.unit = "%"
		item2.descriptionText = "${item1.linkText} dimmed ${item2.value} %"
		item2.canBeCurrentState = true
		item2.isStateChange = isStateChange(device, item2.name, item2.value)
		item2.displayed = false
        
		if (item2.value.toInteger() == lowThresholdvalue) { 
        	sendEvent(name: "currentState", value: "LOW" as String) 
            log.debug "mapitemcurrentStateLow"
        } else if (item2.value.toInteger() == medThresholdvalue) { 
        	sendEvent(name: "currentState", value: "MED" as String)
            log.debug "mapitemcurrentStateMed"
        } else if (item2.value.toInteger() == highThresholdvalue) { 
        	sendEvent(name: "currentState", value: "HIGH" as String) 
            log.debug "mapitemcurrentStateHigh"
        } else if (item2.value.toInteger() == 0) { 
        	sendEvent(name: "currentState", value: "off" as String) 
            log.debug "mapitemcurrentStateOFF"
        } else { 
        	sendEvent(name: "currentState", value: "on" as String) 
            log.debug "mapitemcurrentStateON"
        }

		result << item2
	}
	log.trace "doCreateEvent"
	result
}

def createEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd, Map map) {
//def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
	def value = "when off"
	log.trace "ConfigurationReport"
	if (cmd.configurationValue[0] == 1) {value = "when on"}
	if (cmd.configurationValue[0] == 2) {value = "never"}
	[name: "indicatorStatus", value: value, display: false]
}

def createEvent(physicalgraph.zwave.Command cmd,  Map map) {
	// Handles any Z-Wave commands we aren't interested in
	log.debug "UNHANDLED COMMAND $cmd"
}

def on() {
	log.info "on"
	delayBetween([zwave.basicV1.basicSet(value: 0xFF).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}

def off() {
	log.info "off"
	delayBetween ([zwave.basicV1.basicSet(value: 0x00).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}

def setLevel(value) {
	def lowThresholdvalue = (settings.lowThreshold != null && settings.lowThreshold != "") ? settings.lowThreshold.toInteger() : 33
	def medThresholdvalue = (settings.medThreshold != null && settings.medThreshold != "") ? settings.medThreshold.toInteger() : 67
	def highThresholdvalue = (settings.highThreshold != null && settings.highThreshold != "") ? settings.highThreshold.toInteger() : 99
	
	if (value == "LOW") { value = lowThresholdvalue }
	if (value == "MED") { value = medThresholdvalue }
	if (value == "HIGH") { value = highThresholdvalue }

	def level = Math.min(value as Integer, 99)
    
    if (level == lowThresholdvalue) { 
    	sendEvent(name: "currentState", value: "LOW" as String) 
            log.debug "setLevelcurrentStateLow"
    } else if (level == medThresholdvalue) { 
    	sendEvent(name: "currentState", value: "MED" as String)  
            log.debug "setLevelcurrentStateMed"
    } else if (level == highThresholdvalue) { 
    	sendEvent(name: "currentState", value: "HIGH" as String)  
            log.debug "setLevelcurrentStateHigh"
    } else if (level == 0) { 
    	sendEvent(name: "currentState", value: "off" as String) 
            log.debug "setLevelcurrentStateOFF" 
    } else { 
    	sendEvent(name: "currentState", value: "on" as String) 
            log.debug "setLevelcurrentStateON" 
    }
    
    	sendEvent(name: "level", value: level, unit: "%")
    
    log.trace "setLevelValue: ${value}"
	log.debug "Setting value to: ${currentState}"
    
    delayBetween ([zwave.basicV1.basicSet(value: level as Integer).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 1000)
}

def resetLevel(value) {
    def level = Math.min(value as Integer, 99)
	delayBetween ([
    	delayBetween ([	zwave.basicV1.basicSet(value: level).format(),
        				zwave.basicV1.basicSet(value: 0x00).format()], 10),	
    	zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}

def setLevel(value, duration) {
	def lowThresholdvalue = (settings.lowThreshold != null && settings.lowThreshold != "") ? settings.lowThreshold.toInteger() : 33
	def medThresholdvalue = (settings.medThreshold != null && settings.medThreshold != "") ? settings.medThreshold.toInteger() : 67
	def highThresholdvalue = (settings.highThreshold != null && settings.highThreshold != "") ? settings.highThreshold.toInteger() : 99

	if (value == "LOW") { value = lowThresholdvalue }
	if (value == "MED") { value = medThresholdvalue }
	if (value == "HIGH") { value = highThresholdvalue }

	def level = Math.min(value as Integer, 99)
	def dimmingDuration = duration < 128 ? duration : 128 + Math.round(duration / 60)
	
    if (level == lowThresholdvalue) { 
    	sendEvent(name: "currentState", value: "LOW" as String) 
            log.debug "setLeveldurationcurrentStateLow"
    } else if (level == medThresholdvalue) { 
    	sendEvent(name: "currentState", value: "MED" as String)  
            log.debug "setLeveldurationcurrentStateMed"
    } else if (level == highThresholdvalue) { 
    	sendEvent(name: "currentState", value: "HIGH" as String)  
            log.debug "setLeveldurationcurrentStateHigh"
    } else if (level == 0) { 
    	sendEvent(name: "currentState", value: "off" as String)  
            log.debug "setLeveldurationcurrentStateOFF"
    } else { 
    	sendEvent(name: "currentState", value: "on" as String)  
            log.debug "setLeveldurationcurrentStateON"
    }

    log.trace "setLevelValueDuration: ${value}"
	log.debug "Setting value duration to: ${Level}"
    
	zwave.switchMultilevelV2.switchMultilevelSet(value: level, dimmingDuration: dimmingDuration).format()
}

def levelUp(){

	def steppervalue = (settings.stepper != null && settings.stepper != "") ? settings.stepper.toInteger() : 10
    int nextLevel = device.currentValue("level") + steppervalue
	    
	    if( nextLevel > 100){
	    	nextLevel = 100
	    }
        
		log.trace "setLevelUp(value): ${level}"
	    log.debug "Setting dimmer level up to: ${nextLevel}"
	    delayBetween ([zwave.basicV1.basicSet(value: nextLevel).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 1500)
	}
	
def levelDown(){

	def steppervalue = (settings.stepper != null && settings.stepper != "") ? settings.stepper.toInteger() : 10
    int nextLevel = device.currentValue("level") - steppervalue
	    
	    if (nextLevel < 0){
	    	nextLevel = 0
	    }
	    
	    if (nextLevel == 0){
	    	off()
	    }
        
	    else
	    {
        	log.trace "setLevelDown(value): ${level}"
	    	log.debug "Setting dimmer level down to: ${nextLevel}"
	        delayBetween ([zwave.basicV1.basicSet(value: nextLevel).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 1500)
    }
}

def low() {
	log.trace "setLow"
	setLevel("LOW")
}

def med() {
	log.trace "setMed"
	setLevel("MED")
}

def high() {
	log.trace "setHigh"
	setLevel("HIGH")
}

def poll() {
	zwave.switchMultilevelV1.switchMultilevelGet().format()
}

def refresh() {
	zwave.switchMultilevelV1.switchMultilevelGet().format()
}

def indicatorWhenOn() {
	sendEvent(name: "indicatorStatus", value: "when on", display: false)
	zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 3, size: 1).format()
}

def indicatorWhenOff() {
	sendEvent(name: "indicatorStatus", value: "when off", display: false)
	zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 3, size: 1).format()
}

def indicatorNever() {
	sendEvent(name: "indicatorStatus", value: "never", display: false)
	zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 3, size: 1).format()
}

I have also integrated with Github and will provide the info once I complete the bug fix. This is my first attempt at a device handler but wanted to share as I find the flexibility very useful.

8 Likes

Updated Device type with the bug fixes for multiAttributeTile


/* Dimmer-Switch-Levels.device.groovy
 *
 * Variation of the stock SmartThings "Dimmer-Switch"
 * Variation of the twack "Better-Dimmer-Switch"
 * Variation of the ChadCK "Z-Wave Smart Fan Control"
 *
 * Device type adds set levels low, medium, and High for preset values (Moods).
 * Adds increment up and down buttons with ability to set value.
 *
 * pmjoen@yahoo.com
 * 20160517
 * 
 * v1.2 - Bug fix modify icon for current state in multiAttributeTile 
 * v1.1 - Bug fix showing speed in multiAttributeTile 
 * v1.0 - Initial release of device handler
 *  
*/

metadata {
	// Automatically generated. Make future change here.
	definition (name: "Dimmer-Switch-Levels", namespace: "pmjoen", author: "SmartThings") {
		capability "Switch Level"
		capability "Actuator"
		capability "Indicator"
		capability "Switch"
		capability "Polling"
		capability "Refresh"
		capability "Sensor"

        command "low"
		command "med"
		command "high"
        command "levelUp"
        command "levelDown"

		attribute "currentState", "string"

		//fingerprint deviceId: "0x1101", inClusters: "0x26, 0x27, 0x70, 0x86, 0x72"
	}

		tiles(scale: 2) {
		multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
			tileAttribute ("device.currentState", key: "PRIMARY_CONTROL") {
				attributeState "default", label:'ADJUSTING', action:"refresh.refresh",icon:"st.Lighting.light13", backgroundColor:"#2179b8", nextState: "turningOff"
				attributeState "HIGH", label:'HIGH', action:"switch.off", icon:"st.illuminance.illuminance.bright", backgroundColor:"#79b821", nextState:"turningOff"
				attributeState "MED", label:'MED', action:"switch.off", icon:"st.illuminance.illuminance.light", backgroundColor:"#79b821", nextState:"turningOff" 
				attributeState "LOW", label:'LOW', action:"switch.off", icon:"st.Weather.weather4", backgroundColor:"#79b821", nextState:"turningOff" 
				attributeState "OFF", label:'OFF', action:"switch.on", icon:"st.Lighting.light13", backgroundColor:"#ffffff", nextState: "turningOn"
                attributeState "on", label:'ON', action:"switch.off", icon:"st.Lighting.light11", backgroundColor:"#79b821", nextState:"turningOff"
                attributeState "turningOn", action:"switch.on", label:'TURNINGON', icon:"st.Lighting.light11", backgroundColor:"#2179b8", nextState: "turningOn"
				attributeState "turningOff", action:"switch.off", label:'TURNINGOFF', icon:"st.Lighting.light13", backgroundColor:"#2179b8", nextState: "turningOff"
			}
            
    	tileAttribute("device.level", key: "VALUE_CONTROL") {
                attributeState("VALUE_UP", action: "levelUp")
                attributeState("VALUE_DOWN", action: "levelDown")
			}
		tileAttribute ("device.level", key: "SLIDER_CONTROL") {
				attributeState "level", action:"switch level.setLevel"
			}
		}

		standardTile("indicator", "device.indicatorStatus", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
			state "when off", action:"indicator.indicatorWhenOn", icon:"st.indicators.lit-when-off"
			state "when on", action:"indicator.indicatorNever", icon:"st.indicators.lit-when-on"
			state "never", action:"indicator.indicatorWhenOff", icon:"st.indicators.never-lit"
		}

		standardTile("refresh", "device.switch", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
			state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
		}

		valueTile("level", "device.level", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
			state "level", label:'${currentValue} %', unit:"%", backgroundColor:"#ffffff"
		}

        standardTile("low", "device.currentState", inactiveLabel: false, width: 2, height: 2) {
        	state "default", label: 'LOW', action: "low", icon:"st.Weather.weather4", backgroundColor: "#ffffff"
            state "LOW", label:'LOW', action: "low", icon:"st.Weather.weather4", backgroundColor: "#79b821"
            state "ADJUSTING.LOW", label:'LOW', action: "low", icon:"st.Weather.weather4", backgroundColor: "#2179b8"
  		}
        
        standardTile("med", "device.currentState", inactiveLabel: false, width: 2, height: 2) {
			state "default", label: 'MED', action: "med", icon:"st.illuminance.illuminance.light", backgroundColor: "#ffffff"
            state "MED", label: 'MED', action: "med", icon:"st.illuminance.illuminance.light", backgroundColor: "#79b821"
			state "ADJUSTING.MED", label:'MED', action: "med", icon:"st.illuminance.illuminance.light", backgroundColor: "#2179b8"
		}
            
		standardTile("high", "device.currentState", inactiveLabel: false, width: 2, height: 2) {
			state "default", label: 'HIGH', action: "high", icon:"st.illuminance.illuminance.bright", backgroundColor: "#ffffff"
            state "HIGH", label: 'HIGH', action: "high", icon:"st.illuminance.illuminance.bright", backgroundColor: "#79b821"
            state "ADJUSTING.HIGH", label:'HIGH', action: "high", icon:"st.illuminance.illuminance.bright", backgroundColor: "#2179b8"
		}

		main(["switch"])
        details(["switch", "low", "med", "high", "level", "indicator", "refresh"])
        
	}
    preferences {
		section("Light Level Values") {
			input "lowThreshold", "number", title: "Low Level", range: "1..99"
			input "medThreshold", "number", title: "Medium Level", range: "1..99"
			input "highThreshold", "number", title: "High Level", range: "1..99"
		}
        section ("Interval Selection") {
            input "stepper", "enum", title: "Interval Value", defaultValue: "10", options: ["5","10","20"]
        }
	}
}

def parse(String description) {
	def item1 = [
		canBeCurrentState: false,
		linkText: getLinkText(device),
		isStateChange: false,
		displayed: false,
		descriptionText: description,
		value:  description
	]
	def result
	def cmd = zwave.parse(description, [0x20: 1, 0x26: 1, 0x70: 1])
	if (cmd) {
		result = createEvent(cmd, item1)
	}
	else {
		item1.displayed = displayed(description, item1.isStateChange)
		result = [item1]
	}
	log.debug "Parse returned ${result?.descriptionText}"
	result
}

def createEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd, Map item1) {
	def result = doCreateEvent(cmd, item1)
	for (int i = 0; i < result.size(); i++) {
  	result[i].type = "physical"
	}
	log.trace "BasicReport"
  result
}

def createEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd, Map item1) {
	def result = doCreateEvent(cmd, item1)
	for (int i = 0; i < result.size(); i++) {
		result[i].type = "physical"
	}
	log.trace "BasicSet"
	result
}

def createEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelStartLevelChange cmd, Map item1) {
	[]
	log.trace "StartLevel"
}

def createEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelStopLevelChange cmd, Map item1) {
	[response(zwave.basicV1.basicGet())]
}

def createEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelSet cmd, Map item1) {
	def result = doCreateEvent(cmd, item1)
	for (int i = 0; i < result.size(); i++) {
		result[i].type = "physical"
	}
	log.trace "SwitchMultiLevelSet"
	result
}

def createEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelReport cmd, Map item1) {
	def result = doCreateEvent(cmd, item1)
	result[0].descriptionText = "${item1.linkText} is ${item1.value}"
	result[0].handlerName = cmd.value ? "statusOn" : "statusOff"
	for (int i = 0; i < result.size(); i++) {
		result[i].type = "digital"
	}
	log.trace "SwitchMultilevelReport"
	result
}

def doCreateEvent(physicalgraph.zwave.Command cmd, Map item1) {
	def result = [item1]
	def lowThresholdvalue = (settings.lowThreshold != null && settings.lowThreshold != "") ? settings.lowThreshold.toInteger() : 33
	def medThresholdvalue = (settings.medThreshold != null && settings.medThreshold != "") ? settings.medThreshold.toInteger() : 67
	def highThresholdvalue = (settings.highThreshold != null && settings.highThreshold != "") ? settings.highThreshold.toInteger() : 99

	item1.name = "switch"
	item1.value = cmd.value ? "on" : "off"
	if (item1.value == "off") {
		sendEvent(name: "currentState", value: "OFF" as String)
	}
	item1.handlerName = item1.value
	item1.descriptionText = "${item1.linkText} was turned ${item1.value}"
	item1.canBeCurrentState = true
	item1.isStateChange = isStateChange(device, item1.name, item1.value)
	item1.displayed = false

	if (cmd.value) {
		def item2 = new LinkedHashMap(item1)
		item2.name = "level"
		item2.value = cmd.value as String
		item2.unit = "%"
		item2.descriptionText = "${item1.linkText} dimmed ${item2.value} %"
		item2.canBeCurrentState = true
		item2.isStateChange = isStateChange(device, item2.name, item2.value)
		item2.displayed = false
        
        if (item2.value.toInteger() == lowThresholdvalue) { sendEvent(name: "currentState", value: "LOW" as String) } 
        else if (item2.value.toInteger() == medThresholdvalue) { sendEvent(name: "currentState", value: "MED" as String) } 
        else if (item2.value.toInteger() == highThresholdvalue) { sendEvent(name: "currentState", value: "HIGH" as String) } 
        else if (item2.value.toInteger() == 0) { sendEvent(name: "currentState", value: "OFF" as String) } 
        else { sendEvent(name: "currentState", value: "on" as String) } 

		result << item2
	}
	log.trace "doCreateEvent"
	result
}

def createEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd, Map map) {
//def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
	def value = "when off"
	log.trace "ConfigurationReport"
	if (cmd.configurationValue[0] == 1) {value = "when on"}
	if (cmd.configurationValue[0] == 2) {value = "never"}
	[name: "indicatorStatus", value: value, display: false]
}

def createEvent(physicalgraph.zwave.Command cmd,  Map map) {
	// Handles any Z-Wave commands we aren't interested in
	log.debug "UNHANDLED COMMAND $cmd"
}

def on() {
	log.info "on"
	delayBetween([zwave.basicV1.basicSet(value: 0xFF).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}

def off() {
	log.info "off"
	delayBetween ([zwave.basicV1.basicSet(value: 0x00).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}

def setLevel(value) {
	def lowThresholdvalue = (settings.lowThreshold != null && settings.lowThreshold != "") ? settings.lowThreshold.toInteger() : 33
	def medThresholdvalue = (settings.medThreshold != null && settings.medThreshold != "") ? settings.medThreshold.toInteger() : 67
	def highThresholdvalue = (settings.highThreshold != null && settings.highThreshold != "") ? settings.highThreshold.toInteger() : 99
	
	if (value == "LOW") { value = lowThresholdvalue }
	if (value == "MED") { value = medThresholdvalue }
	if (value == "HIGH") { value = highThresholdvalue }

	def level = Math.min(value as Integer, 99)
    
    if (level == lowThresholdvalue) { sendEvent(name: "currentState", value: "ADJUSTING.LOW" as String, displayed: false) } 
    else if (level == medThresholdvalue) { sendEvent(name: "currentState", value: "ADJUSTING.MED" as String, displayed: false) } 
    else if (level == highThresholdvalue) { sendEvent(name: "currentState", value: "ADJUSTING.HIGH" as String, displayed: false) } 
    else if (level == 0) { sendEvent(name: "currentState", value: "OFF" as String, displayed: false) } 
    else { sendEvent(name: "currentState", value: "on" as String, displayed: false) } 
    
    sendEvent(name: "level", value: level, unit: "%")
    
    log.trace "setLevelValue: ${value}"
	log.debug "Setting value to: ${currentState}"
    
    delayBetween ([zwave.basicV1.basicSet(value: level as Integer).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 1000)
}

def resetLevel(value) {
    def level = Math.min(value as Integer, 99)
	delayBetween ([
    	delayBetween ([	zwave.basicV1.basicSet(value: level).format(),
        				zwave.basicV1.basicSet(value: 0x00).format()], 10),	
    	zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}

def setLevel(value, duration) {
	def lowThresholdvalue = (settings.lowThreshold != null && settings.lowThreshold != "") ? settings.lowThreshold.toInteger() : 33
	def medThresholdvalue = (settings.medThreshold != null && settings.medThreshold != "") ? settings.medThreshold.toInteger() : 67
	def highThresholdvalue = (settings.highThreshold != null && settings.highThreshold != "") ? settings.highThreshold.toInteger() : 99

	if (value == "LOW") { value = lowThresholdvalue }
	if (value == "MED") { value = medThresholdvalue }
	if (value == "HIGH") { value = highThresholdvalue }

	def level = Math.min(value as Integer, 99)
	def dimmingDuration = duration < 128 ? duration : 128 + Math.round(duration / 60)
    
    if (level == lowThresholdvalue) { sendEvent(name: "currentState", value: "ADJUSTING.LOW" as String, displayed: false) } 
    else if (level == medThresholdvalue) { sendEvent(name: "currentState", value: "ADJUSTING.MED" as String, displayed: false) } 
    else if (level == highThresholdvalue) { sendEvent(name: "currentState", value: "ADJUSTING.HIGH" as String, displayed: false) }
    else if (level == 0) { sendEvent(name: "currentState", value: "OFF" as String, displayed: false) } 
    else { sendEvent(name: "currentState", value: "on" as String, displayed: false) } 

    log.trace "setLevelValueDuration: ${value}"
	log.debug "Setting value duration to: ${Level}"
    
	zwave.switchMultilevelV2.switchMultilevelSet(value: level, dimmingDuration: dimmingDuration).format()
}

def levelUp(){

	def steppervalue = (settings.stepper != null && settings.stepper != "") ? settings.stepper.toInteger() : 10
    int nextLevel = device.currentValue("level") + steppervalue
	    
	    if( nextLevel > 100){
	    	nextLevel = 100
	    }
        
		log.trace "setLevelUp(value): ${level}"
	    log.debug "Setting dimmer level up to: ${nextLevel}"
	    delayBetween ([zwave.basicV1.basicSet(value: nextLevel).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 1500)
	}
	
def levelDown(){

	def steppervalue = (settings.stepper != null && settings.stepper != "") ? settings.stepper.toInteger() : 10
    int nextLevel = device.currentValue("level") - steppervalue
	    
	    if (nextLevel < 0){
	    	nextLevel = 0
	    }
	    
	    if (nextLevel == 0){
	    	off()
	    }
        
	    else
	    {
        	log.trace "setLevelDown(value): ${level}"
	    	log.debug "Setting dimmer level down to: ${nextLevel}"
	        delayBetween ([zwave.basicV1.basicSet(value: nextLevel).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 1500)
    }
}

def low() {
	log.trace "setLow"
	setLevel("LOW")
}

def med() {
	log.trace "setMed"
	setLevel("MED")
}

def high() {
	log.trace "setHigh"
	setLevel("HIGH")
}

def poll() {
	zwave.switchMultilevelV1.switchMultilevelGet().format()
}

def refresh() {
	zwave.switchMultilevelV1.switchMultilevelGet().format()
}

def indicatorWhenOn() {
	sendEvent(name: "indicatorStatus", value: "when on", display: false)
	zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 3, size: 1).format()
}

def indicatorWhenOff() {
	sendEvent(name: "indicatorStatus", value: "when off", display: false)
	zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 3, size: 1).format()
}

def indicatorNever() {
	sendEvent(name: "indicatorStatus", value: "never", display: false)
	zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 3, size: 1).format()
}

Other improvements working on.

  • Changed icon not saving.
  • Slider control set current state adjusting before updates.
  • Interval change set current state adjusting before updates.

Very nice! This should be the ST default dimmer handler. I know the chance is low but are you going to submit this to ST? Local processing of this device handler would be sweet.

1 Like

I have fixed the previous bugs and provide the full code below, hope everyone enjoys. This is my first device handler, so I’m sure a proficient developer could clean the code up but its working as designed.


/* Dimmer-Switch-Levels.device.groovy
 *
 * Variation of the stock SmartThings "Dimmer-Switch"
 * Variation of the twack "Better-Dimmer-Switch"
 * Variation of the ChadCK "Z-Wave Smart Fan Control"
 *
 * Device type adds set levels low, medium, and High for preset values (Moods).
 * Adds increment up and down buttons with ability to set value.
 *
 * pmjoen@yahoo.com
 * 20160517
 *
 * v1.3 - Improvement select stepper value up/down shows adjusting in multiAttributeTile
 * v1.2 - Bug fix modify icon for current state in multiAttributeTile 
 * v1.1 - Bug fix showing speed in multiAttributeTile 
 * v1.0 - Initial release of device handler
 *  
*/

metadata {
	// Automatically generated. Make future change here.
	definition (name: "Dimmer-Switch-Levels", namespace: "pmjoen", author: "SmartThings") {
		capability "Switch Level"
		capability "Actuator"
		capability "Indicator"
		capability "Switch"
		capability "Polling"
		capability "Refresh"
		capability "Sensor"

        command "low"
		command "med"
		command "high"
        command "levelUp"
        command "levelDown"

		attribute "currentState", "string"
        attribute "switch", "string"

		//fingerprint deviceId: "0x1101", inClusters: "0x26, 0x27, 0x70, 0x86, 0x72"
	}

		tiles(scale: 2) {
		multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
			tileAttribute ("device.currentState", key: "PRIMARY_CONTROL") {
				attributeState "default", label:'ADJUSTING', action:"refresh.refresh",icon:"st.Lighting.light13", backgroundColor:"#2179b8", nextState: "turningOff"
				attributeState "HIGH", label:'HIGH', action:"switch.off", icon:"st.illuminance.illuminance.bright", backgroundColor:"#79b821", nextState:"turningOff"
				attributeState "MED", label:'MED', action:"switch.off", icon:"st.illuminance.illuminance.light", backgroundColor:"#79b821", nextState:"turningOff" 
				attributeState "LOW", label:'LOW', action:"switch.off", icon:"st.Weather.weather4", backgroundColor:"#79b821", nextState:"turningOff" 
				attributeState "OFF", label:'OFF', action:"switch.on", icon:"st.Lighting.light13", backgroundColor:"#ffffff", nextState: "turningOn"
                attributeState "on", label:'ON', action:"switch.off", icon:"st.Lighting.light11", backgroundColor:"#79b821", nextState:"turningOff"
                attributeState "turningOn", action:"switch.on", label:'TURNINGON', icon:"st.Lighting.light11", backgroundColor:"#2179b8", nextState: "turningOn"
				attributeState "turningOff", action:"switch.off", label:'TURNINGOFF', icon:"st.Lighting.light13", backgroundColor:"#2179b8", nextState: "turningOff"
			}
            
    	tileAttribute("device.level", key: "VALUE_CONTROL") {
                attributeState("VALUE_UP", action: "levelUp")
                attributeState("VALUE_DOWN", action: "levelDown")
			}
		tileAttribute ("device.level", key: "SLIDER_CONTROL") {
				attributeState "level", action:"switch level.setLevel"
			}
		}

		standardTile("indicator", "device.indicatorStatus", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
			state "when off", action:"indicator.indicatorWhenOn", icon:"st.indicators.lit-when-off"
			state "when on", action:"indicator.indicatorNever", icon:"st.indicators.lit-when-on"
			state "never", action:"indicator.indicatorWhenOff", icon:"st.indicators.never-lit"
		}

		standardTile("refresh", "device.switch", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
			state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
		}

		valueTile("level", "device.level", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
			state "level", label:'${currentValue} %', unit:"%", backgroundColor:"#ffffff"
		}

        standardTile("low", "device.currentState", inactiveLabel: false, width: 2, height: 2, canChangeBackground: false) {
        	state "default", label: 'LOW', action: "low", icon:"st.Weather.weather4", backgroundColor: "#ffffff"
            state "LOW", label:'LOW', action: "low", icon:"st.Weather.weather4", backgroundColor: "#79b821"
            state "ADJUSTING.LOW", label:'LOW', action: "low", icon:"st.Weather.weather4", backgroundColor: "#2179b8"
  		}
        
        standardTile("med", "device.currentState", inactiveLabel: false, width: 2, height: 2, canChangeBackground: false) {
			state "default", label: 'MED', action: "med", icon:"st.illuminance.illuminance.light", backgroundColor: "#ffffff"
            state "MED", label: 'MED', action: "med", icon:"st.illuminance.illuminance.light", backgroundColor: "#79b821"
			state "ADJUSTING.MED", label:'MED', action: "med", icon:"st.illuminance.illuminance.light", backgroundColor: "#2179b8"
		}
            
		standardTile("high", "device.currentState", inactiveLabel: false, width: 2, height: 2, canChangeBackground: false) {
			state "default", label: 'HIGH', action: "high", icon:"st.illuminance.illuminance.bright", backgroundColor: "#ffffff"
            state "HIGH", label: 'HIGH', action: "high", icon:"st.illuminance.illuminance.bright", backgroundColor: "#79b821"
            state "ADJUSTING.HIGH", label:'HIGH', action: "high", icon:"st.illuminance.illuminance.bright", backgroundColor: "#2179b8"
		}

		main(["switch"])
        details(["switch", "low", "med", "high", "level", "indicator", "refresh"])
        
	}
    preferences {
		section("Light Level Values") {
			input "lowThreshold", "number", title: "Low Level", range: "1..99"
			input "medThreshold", "number", title: "Medium Level", range: "1..99"
			input "highThreshold", "number", title: "High Level", range: "1..99"
		}
        section ("Interval Selection") {
            input "stepper", "enum", title: "Interval Value", defaultValue: "10", options: ["5","10","20"]
        }
	}
}

def parse(String description) {
	def item1 = [
		canBeCurrentState: false,
		linkText: getLinkText(device),
		isStateChange: false,
		displayed: false,
		descriptionText: description,
		value:  description
	]
	def result
	def cmd = zwave.parse(description, [0x20: 1, 0x26: 1, 0x70: 1])
	if (cmd) {
		result = createEvent(cmd, item1)
	}
	else {
		item1.displayed = displayed(description, item1.isStateChange)
		result = [item1]
	}
	log.debug "Parse returned ${result?.descriptionText}"
	result
}

def createEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd, Map item1) {
	def result = doCreateEvent(cmd, item1)
	for (int i = 0; i < result.size(); i++) {
  	result[i].type = "physical"
	}
	log.trace "BasicReport"
  result
}

def createEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd, Map item1) {
	def result = doCreateEvent(cmd, item1)
	for (int i = 0; i < result.size(); i++) {
		result[i].type = "physical"
	}
	log.trace "BasicSet"
	result
}

def createEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelStartLevelChange cmd, Map item1) {
	[]
	log.trace "StartLevel"
}

def createEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelStopLevelChange cmd, Map item1) {
	[response(zwave.basicV1.basicGet())]
}

def createEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelSet cmd, Map item1) {
	def result = doCreateEvent(cmd, item1)
	for (int i = 0; i < result.size(); i++) {
		result[i].type = "physical"
	}
	log.trace "SwitchMultiLevelSet"
	result
}

def createEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelReport cmd, Map item1) {
	def result = doCreateEvent(cmd, item1)
	result[0].descriptionText = "${item1.linkText} is ${item1.value}"
	result[0].handlerName = cmd.value ? "statusOn" : "statusOff"
	for (int i = 0; i < result.size(); i++) {
		result[i].type = "digital"
	}
	log.trace "SwitchMultilevelReport"
	result
}

def doCreateEvent(physicalgraph.zwave.Command cmd, Map item1) {
	def result = [item1]
	def lowThresholdvalue = (settings.lowThreshold != null && settings.lowThreshold != "") ? settings.lowThreshold.toInteger() : 33
	def medThresholdvalue = (settings.medThreshold != null && settings.medThreshold != "") ? settings.medThreshold.toInteger() : 67
	def highThresholdvalue = (settings.highThreshold != null && settings.highThreshold != "") ? settings.highThreshold.toInteger() : 99

	item1.name = "switch"
	item1.value = cmd.value ? "on" : "off"
	if (item1.value == "off") {
		sendEvent(name: "currentState", value: "OFF" as String)
	}
	item1.handlerName = item1.value
	item1.descriptionText = "${item1.linkText} was turned ${item1.value}"
	item1.canBeCurrentState = true
	item1.isStateChange = isStateChange(device, item1.name, item1.value)
	item1.displayed = false

	if (cmd.value) {
		def item2 = new LinkedHashMap(item1)
		item2.name = "level"
		item2.value = cmd.value as String
		item2.unit = "%"
		item2.descriptionText = "${item1.linkText} dimmed ${item2.value} %"
		item2.canBeCurrentState = true
		item2.isStateChange = isStateChange(device, item2.name, item2.value)
		item2.displayed = false
        
        if (item2.value.toInteger() == lowThresholdvalue) { sendEvent(name: "currentState", value: "LOW" as String) } 
        else if (item2.value.toInteger() == medThresholdvalue) { sendEvent(name: "currentState", value: "MED" as String) } 
        else if (item2.value.toInteger() == highThresholdvalue) { sendEvent(name: "currentState", value: "HIGH" as String) } 
        else if (item2.value.toInteger() == 0) { sendEvent(name: "currentState", value: "OFF" as String) } 
        else { sendEvent(name: "currentState", value: "on" as String) } 

		result << item2
	}
	log.trace "doCreateEvent"
	result
}

def createEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd, Map map) {
//def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
	def value = "when off"
	log.trace "ConfigurationReport"
	if (cmd.configurationValue[0] == 1) {value = "when on"}
	if (cmd.configurationValue[0] == 2) {value = "never"}
	[name: "indicatorStatus", value: value, display: false]
}

def createEvent(physicalgraph.zwave.Command cmd,  Map map) {
	// Handles any Z-Wave commands we aren't interested in
	log.debug "UNHANDLED COMMAND $cmd"
}

def on() {
	log.info "on"
	delayBetween([zwave.basicV1.basicSet(value: 0xFF).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}

def off() {
	log.info "off"
	delayBetween ([zwave.basicV1.basicSet(value: 0x00).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}

def setLevel(value) {
	def lowThresholdvalue = (settings.lowThreshold != null && settings.lowThreshold != "") ? settings.lowThreshold.toInteger() : 33
	def medThresholdvalue = (settings.medThreshold != null && settings.medThreshold != "") ? settings.medThreshold.toInteger() : 67
	def highThresholdvalue = (settings.highThreshold != null && settings.highThreshold != "") ? settings.highThreshold.toInteger() : 99
	
	if (value == "LOW") { value = lowThresholdvalue }
	if (value == "MED") { value = medThresholdvalue }
	if (value == "HIGH") { value = highThresholdvalue }

	def level = Math.min(value as Integer, 99)
    
    if (level == lowThresholdvalue) { sendEvent(name: "currentState", value: "ADJUSTING.LOW" as String, displayed: false) } 
    else if (level == medThresholdvalue) { sendEvent(name: "currentState", value: "ADJUSTING.MED" as String, displayed: false) } 
    else if (level == highThresholdvalue) { sendEvent(name: "currentState", value: "ADJUSTING.HIGH" as String, displayed: false) } 
    else if (level == 0) { sendEvent(name: "currentState", value: "OFF" as String, displayed: false) } 
    else { sendEvent(name: "currentState", value: "on" as String, displayed: false) } 
    
    sendEvent(name: "level", value: level, unit: "%")
    
    log.trace "setLevelValue: ${value}"
    
    delayBetween ([zwave.basicV1.basicSet(value: level as Integer).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 1000)
}

def resetLevel(value) {
    def level = Math.min(value as Integer, 99)
	delayBetween ([
    	delayBetween ([	zwave.basicV1.basicSet(value: level).format(),
        				zwave.basicV1.basicSet(value: 0x00).format()], 10),	
    	zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}

def setLevel(value, duration) {
	def lowThresholdvalue = (settings.lowThreshold != null && settings.lowThreshold != "") ? settings.lowThreshold.toInteger() : 33
	def medThresholdvalue = (settings.medThreshold != null && settings.medThreshold != "") ? settings.medThreshold.toInteger() : 67
	def highThresholdvalue = (settings.highThreshold != null && settings.highThreshold != "") ? settings.highThreshold.toInteger() : 99

	if (value == "LOW") { value = lowThresholdvalue }
	if (value == "MED") { value = medThresholdvalue }
	if (value == "HIGH") { value = highThresholdvalue }

	def level = Math.min(value as Integer, 99)
	def dimmingDuration = duration < 128 ? duration : 128 + Math.round(duration / 60)
    
    if (level == lowThresholdvalue) { sendEvent(name: "currentState", value: "ADJUSTING.LOW" as String, displayed: false) } 
    else if (level == medThresholdvalue) { sendEvent(name: "currentState", value: "ADJUSTING.MED" as String, displayed: false) } 
    else if (level == highThresholdvalue) { sendEvent(name: "currentState", value: "ADJUSTING.HIGH" as String, displayed: false) }
    else if (level == 0) { sendEvent(name: "currentState", value: "OFF" as String, displayed: false) } 
    else { sendEvent(name: "currentState", value: "on" as String, displayed: false) } 

    log.trace "setLevelValueDuration: ${value}"
    
	zwave.switchMultilevelV2.switchMultilevelSet(value: level, dimmingDuration: dimmingDuration).format()
}

def levelUp(){

	def steppervalue = (settings.stepper != null && settings.stepper != "") ? settings.stepper.toInteger() : 10
    int nextLevel = device.currentValue("level") + steppervalue
    sendEvent(name: "currentState", value: "default" as String, displayed: false)  
	    
	    if( nextLevel > 100){
	    	nextLevel = 100
	    }
        
		log.trace "setLevelUp(value): ${level}"
	    log.debug "Setting dimmer level up to: ${nextLevel}"
	    delayBetween ([zwave.basicV1.basicSet(value: nextLevel).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 1500)
	}
	
def levelDown(){

	def steppervalue = (settings.stepper != null && settings.stepper != "") ? settings.stepper.toInteger() : 10
    int nextLevel = device.currentValue("level") - steppervalue
	sendEvent(name: "currentState", value: "default" as String, displayed: false)  
    
	    if (nextLevel < 0){
	    	nextLevel = 0
	    }
	    
	    if (nextLevel == 0){
	    	off()
	    }
        
	    else
	    {
        	log.trace "setLevelDown(value): ${level}"
	    	log.debug "Setting dimmer level down to: ${nextLevel}"
	        delayBetween ([zwave.basicV1.basicSet(value: nextLevel).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 1500)
    }
}

def low() {
	log.trace "setLow"
	setLevel("LOW")
}

def med() {
	log.trace "setMed"
	setLevel("MED")
}

def high() {
	log.trace "setHigh"
	setLevel("HIGH")
}

def poll() {
	zwave.switchMultilevelV1.switchMultilevelGet().format()
}

def refresh() {
	zwave.switchMultilevelV1.switchMultilevelGet().format()
}

def indicatorWhenOn() {
	sendEvent(name: "indicatorStatus", value: "when on", display: false)
	zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 3, size: 1).format()
}

def indicatorWhenOff() {
	sendEvent(name: "indicatorStatus", value: "when off", display: false)
	zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 3, size: 1).format()
}

def indicatorNever() {
	sendEvent(name: "indicatorStatus", value: "never", display: false)
	zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 3, size: 1).format()
}

Thanks for the feedback, and since this is my first device handler I’m sure it would not meet their standards for coding. So here it is with all the fixes and is now working as designed.

This looks good, will test when I get home. I have a problem where my LED lights flicker when the % is low like 10% and for some reason, it was always defaulting to that. Also on the edit screen for the device, I see Interval Value and a whole bunch of other numbers listed but I am not sure what they mean, there is no labels.

Finally - I recommend you post your code up on GitHub and allow us to sync to it.

That is odd, I don’t have code for the additional preference fields you see… Ive seen this occur when you switch from one device handler (That has more preference options) to a newer device handler. Also need to figure out the github thing as its not working for me.

Good call. I was previously using @desertblade’s Enhanced Dimmer device type. I had to go into each of those values and remove them. Now I have the proper values. What does interval Value do though?

The interval value controls the up and down arrow value in the detail of the switch allowing you to set if you want them to use 5, 10, or 20 as the incremental value to go up and down… Just a way for you to customize your switch how you want. Let me know if you think you would want to see any other values. I assumed less then 5 is not useful and more than 20 might be wasteful (10 is set as default). Any suggestions on the verbiage for that, i wasn’t quote sure…

This is an excellent device type! It works extremely well on my GE and Leviton dimmers I have. I often struggled with what level sometimes to put my lights at and it’s really nice to have 3 preset levels. It also helped me with my problem where the Commercial Electric LED trims I have flicker at a very low level (10%) as now they are defaulting to whatever I leave it on last. As far as verbiage for the “interval value”, I would call it “+/- value”. Seems self explanatory if you see it like that. I think 10 is the perfect setting,

Now I didn’t look at the code yet, but can you actually use these “low” values as a custom command in Rule Machine? My guess is not.

I am using my Low at 15, Medium at 40 and High at 80, but until it’s dark and I test every room, it might change based on conditions. For my sons room, I am using 1%, 15% and 80% since he doesn’t like to sleep in the dark yet.

One of the issues I am having is using the physical switch to dim. It goes from 1% to 99% and can’t adjust it in between. It’s just happening in one of my rooms even though I have an identical setup in other rooms. This is the same room with the flickering issue if I have them less than 10%. Does anyone have this issue?

I have now integrated with github

Owner:
pmjoen
Name:
SmartThingsPublic
Branch:
Master

Thanks. I would try to avoid naming your repo “SmartThingsPublic” as that is the default name that a lot of developers are now using. Unfortunatelty, the IDE does a very poor job of distinguishing the different repositories and you end up with multiple repo’s named the same thing and updating your code becomes a chore.

I have submitted this device handler for publication on ST.

I agree it is very tedious to update the code in this case, but this is what the documentation asks for github integration.

I have 4 dimmers using your device handler and very happy with it so far. Sometime there is delay on changing dimming level but that’s because of ST and cloud. Really like the colors and icons.
I don’t think anyone following ST and github with smartthingspublic. It’s a mess.

I’m glad others find it more useful than the standard, I was thinking about changing the colors from green when on to different shades of yellow (depending on level). What are your thoughts or any other suggestions to improve?

1 Like

Different colors for each level would be really nice. Maybe user selectable if possible.
Not sure you want to add too many stuffs to a device handler with ST but a blink or strobe option is also handy.