Skip to end of metadata
Go to start of metadata

Information and code on adding FC200 to SmartThings


Go to this URL and log in with SmartThings account: https://graph-na04-useast2.api.smartthings.com

Click on the "My Device Handlers" menu 
Click "Create New Device Handler" on the right 
Click "From Code" 
Click here to view the code on GitHub
Click "Create" at the bottom 
Click "Publish" and select "For Me" 

Now add the FC200 to the SmartThings app and verify that it shows the multitap tiles. These tiles do not do anything, but tapping the paddle will display the number of taps on the screen.  
Click the Gear icon to adjust settings such as default LED color. 
The switch shows up in SmartThings as supporting 12 buttons, the buttons can be used as triggers as follows: 

ACTION BUTTON

  1. Double-Tap Up
  2. Double-Tap Down
  3. Triple-Tap Up
  4. Triple-Tap Down
  5. Hold Up
  6. Hold Down
  7. Single-Tap Up
  8. Single-Tap Down
  9. 4 taps up
  10. 4 taps down
  11. 5 taps up
  12. 5 taps down

To use set the status mode LEDS and blink, you need to install the CoRE SmartApp, directions are here: 
http://thingsthataresmart.wiki/index.php?title=CoRE (The manual installation is easiest) 
To control the LEDS on the switch, add an new piston set the trigger to whatever you want (maybe a button on the switch) 

Add an action and select the switch for the action, a list of actions will appear, there are some custom actions: 

setSwitchModeNormal() Sets the switch to Normal mode, disables status display 
setSwitchModeStatus() Sets the switch to Status mode and will display any LEDS that are enabled 
setDefaultColor(color) Sets the default color of ALL LEDS in Normal mode color parameter is a #: 

  • 0=White 
  • 1=Red 
  • 2=Green 
  • 3=Blue 
  • 4=Magenta
  • 5=Yellow 
  • 6=Cyan

setStatusLed (led,color,blink) Sets a specific LED to a specific color and sets it to blink or not to blinkled parameter is the led # to set (1-4)  
color parameter is a # which is the color to set: 

  • 0=Off 
  • 1=Red
  • 2=Green 
  • 3=Blue 
  • 4=Magenta 
  • 5=Yellow 
  • 6=Cyan 
  • 7=White 

blink parameter is 1 to blink and 0 to no blink 

When any LED is set, the switch to put into status mode. When all LEDS are set to OFF, the switch goes back to Normal mode

For additional help on using the RGB LEDs, see the videos below.

FC200
/**
 *  HomeSeer HS-FC200+
 *
 *  Copyright 2018 DarwinsDen.com, HomeSeer, @aruffell 
 *
 *  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.
 *
 *	Author: Darwin@DarwinsDen.com, HomeSeer, @aruffell, with fan control button code leveraged from @ChadCK
 *	Date: 2018-18-Oct
 *
 *	Changelog:
 *    1.0 Oct 2018 Initial Version based on WD200+
 *
 *   Button Mappings:
 *
 *   ACTION          BUTTON#    BUTTON ACTION
 *   Double-Tap Up     1        pressed
 *   Double-Tap Down   2        pressed
 *   Triple-Tap Up     3        pressed
 *   Triple-Tap Down   4        pressed
 *   Hold Up           5 	    pressed
 *   Hold Down         6 	    pressed
 *   Single-Tap Up     7        pressed
 *   Single-Tap Down   8        pressed
 *   4 taps up         9        pressed
 *   4 taps down       10       pressed
 *   5 taps up         11       pressed
 *   5 taps down       12       pressed
 **/

metadata {
    definition(name: "HomeSeer FC200+ Fan Controller", namespace: "darwinsden", author: "darwin@darwinsden.com") {
        capability "Switch Level"
        capability "Actuator"
        capability "Indicator"
        capability "Switch"
        capability "Polling"
        capability "Refresh"
        capability "Sensor"
        capability "Button"
        capability "Configuration"
        
        command "lowSpeed"
		command "medSpeed"
		command "highSpeed"

        command "tapUp2"
        command "tapDown2"
        command "tapUp3"
        command "tapDown3"
        command "tapUp4"
        command "tapDown4"
        command "tapUp5"
        command "tapDown5"
        command "holdUp"
        command "holdDown"
        command "setStatusLed"
        command "setSwitchModeNormal"
        command "setSwitchModeStatus"
        command "setDefaultColor"
        command "setBlinkDurationMilliseconds"

        fingerprint mfr: "000C", prod: "0203", model: "0001"

    }

    simulator {
        status "on": "command: 2003, payload: FF"
        status "off": "command: 2003, payload: 00"
        status "09%": "command: 2003, payload: 09"
        status "10%": "command: 2003, payload: 0A"
        status "33%": "command: 2003, payload: 21"
        status "66%": "command: 2003, payload: 42"
        status "99%": "command: 2003, payload: 63"

        // reply messages
        reply "2001FF,delay 5000,2602": "command: 2603, payload: FF"
        reply "200100,delay 5000,2602": "command: 2603, payload: 00"
        reply "200119,delay 5000,2602": "command: 2603, payload: 19"
        reply "200132,delay 5000,2602": "command: 2603, payload: 32"
        reply "20014B,delay 5000,2602": "command: 2603, payload: 4B"
        reply "200163,delay 5000,2602": "command: 2603, payload: 63"
    }

    preferences {
        input "doubleTapToFullSpeed", "bool", title: "Double-Tap Up sets to full speed", defaultValue: false, displayDuringSetup: true, required: false
        input "singleTapToFullSpeed", "bool", title: "Single-Tap Up sets to full speed", defaultValue: false, displayDuringSetup: true, required: false
        input "doubleTapDownToDim", "bool", title: "Double-Tap Down sets to 25% speed", defaultValue: false, displayDuringSetup: true, required: false
        input "enable4FanSpeeds", "bool", title: "Enable 4 fan speed mode", defaultValue: false, displayDuringSetup: true, required: false
        input "reverseSwitch", "bool", title: "Reverse Switch", defaultValue: false, displayDuringSetup: true, required: false
        input "bottomled", "bool", title: "Bottom LED On if Load is Off", defaultValue: false, displayDuringSetup: true, required: false
        input("color", "enum", title: "Default LED Color", options: ["White", "Red", "Green", "Blue", "Magenta", "Yellow", "Cyan"], description: "Select Color", required: false)
		section("Fan Thresholds") {
			input "lowThreshold", "number", title: "Low Threshold", range: "1..99"
			input "medThreshold", "number", title: "Medium Threshold", range: "1..99"
			input "highThreshold", "number", title: "High Threshold", range: "1..99"
		}
}

    tiles(scale: 2) {
        multiAttributeTile(name: "switch", type: "lighting", width: 6, height: 4, canChangeIcon: true) {
            tileAttribute("device.switch", key: "PRIMARY_CONTROL") {
                attributeState "on", label: '${name}', action: "switch.off", icon: "st.Home.home30", backgroundColor: "#79b821", nextState: "turningOff"
                attributeState "off", label: '${name}', action: "switch.on", icon: "st.Home.home30", backgroundColor: "#ffffff", nextState: "turningOn"
                attributeState "turningOn", label: '${name}', action: "switch.off", icon: "st.Home.home30", backgroundColor: "#79b821", nextState: "turningOff"
                attributeState "turningOff", label: '${name}', action: "switch.on", icon: "st.Home.home30", backgroundColor: "#ffffff", nextState: "turningOn"
            }
            tileAttribute("device.level", key: "SLIDER_CONTROL") {
                attributeState "level", action: "switch level.setLevel"
            }
            tileAttribute("device.status", key: "SECONDARY_CONTROL") {
                attributeState("default", label: '${currentValue}', unit: "")
            }
        }

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

        valueTile("firmwareVersion", "device.firmwareVersion", width: 2, height: 2, decoration: "flat", inactiveLabel: false) {
            state "default", label: '${currentValue}'
        }

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

	    standardTile("lowSpeed", "device.currentState", inactiveLabel: false, width: 2, height: 2) {
			state "default", label: 'LOW', action: "lowSpeed", icon:"st.Home.home30", backgroundColor: "#ffffff"
			state "LOW", label:'LOW', action: "lowSpeed", icon:"st.Home.home30", backgroundColor: "#79b821"
			state "ADJUSTING.LOW", label:'LOW', action: "lowSpeed", icon:"st.Home.home30", backgroundColor: "#2179b8"
  		}
        
		standardTile("medSpeed", "device.currentState", inactiveLabel: false, width: 2, height: 2) {
			state "default", label: 'MED', action: "medSpeed", icon:"st.Home.home30", backgroundColor: "#ffffff"
			state "MED", label: 'MED', action: "medSpeed", icon:"st.Home.home30", backgroundColor: "#79b821"
			state "ADJUSTING.MED", label:'MED', action: "medSpeed", icon:"st.Home.home30", backgroundColor: "#2179b8"
		}
        
		standardTile("highSpeed", "device.currentState", inactiveLabel: false, width: 2, height: 2) {
			state "default", label: 'HIGH', action: "highSpeed", icon:"st.Home.home30", backgroundColor: "#ffffff"
			state "HIGH", label: 'HIGH', action: "highSpeed", icon:"st.Home.home30", backgroundColor: "#79b821"
			state "ADJUSTING.HIGH", label:'HIGH', action: "highSpeed", icon:"st.Home.home30", backgroundColor: "#2179b8"
        }
 
        valueTile("tapUp2", "device.button", width: 1, height: 1, decoration: "flat") {
            state "default", label: "Button 1\nTap\n▲▲", backgroundColor: "#ffffff", action: "tapUp2"
        }

        valueTile("tapDown2", "device.button", width: 1, height: 1, decoration: "flat") {
            state "default", label: "Button 2\nTap\n▼▼", backgroundColor: "#ffffff", action: "tapDown2"
        }

        valueTile("tapUp3", "device.button", width: 1, height: 1, decoration: "flat") {
            state "default", label: "Button 3\nTap\n▲▲▲", backgroundColor: "#ffffff", action: "tapUp3"
        }

        valueTile("tapDown3", "device.button", width: 1, height: 1, decoration: "flat") {
            state "default", label: "Button 4\nTap\n▼▼▼", backgroundColor: "#ffffff", action: "tapDown3"
        }
        valueTile("tapUp1", "device.button", width: 1, height: 1, decoration: "flat") {
            state "default", label: "Button 7\nTap\n▲", backgroundColor: "#ffffff", action: "tapUp1"
        }

        valueTile("tapDown1", "device.button", width: 1, height: 1, decoration: "flat") {
            state "default", label: "Button 8\nTap\n▼", backgroundColor: "#ffffff", action: "tapDown1"
        }

        valueTile("tapUp4", "device.button", width: 1, height: 1, decoration: "flat") {
            state "default", label: "Button 9\nTap\n▲▲▲▲", backgroundColor: "#ffffff", action: "tapUp4"
        }

        valueTile("tapDown4", "device.button", width: 1, height: 1, decoration: "flat") {
            state "default", label: "Button 10\nTap\n▼▼▼▼", backgroundColor: "#ffffff", action: "tapDown4"
        }

        valueTile("tapUp5", "device.button", width: 1, height: 1, decoration: "flat") {
            state "default", label: "Button 11\nTap\n▲▲▲▲▲", backgroundColor: "#ffffff", action: "tapUp5"
        }

        valueTile("tapDown5", "device.button", width: 1, height: 1, decoration: "flat") {
            state "default", label: "Button 12\nTap\n▼▼▼▼▼", backgroundColor: "#ffffff", action: "tapDown5"
        }

        valueTile("holdUp", "device.button", width: 1, height: 1, decoration: "flat") {
            state "default", label: "Button 5\nHold\n▲", backgroundColor: "#ffffff", action: "holdUp"
        }

        valueTile("holdDown", "device.button", width: 1, height: 1, decoration: "flat") {
            state "default", label: "Button 6\nHold\n▼", backgroundColor: "#ffffff", action: "holdDown"
        }

        main(["switch"])

        details(["switch", "lowSpeed", "medSpeed", "highSpeed", "tapUp2", "tapDown2", "tapUp3", "tapDown3", "holdUp", "holdDown", "tapUp1", "tapDown1", "tapUp4", "tapDown4", "tapUp5", "tapDown5", "level", "firmwareVersion", "refresh"])
    }

}

def parse(String description) {
    def result = null
    log.debug(description)
    if (description != "updated") {
        def cmd = zwave.parse(description, [0x20: 1, 0x26: 1, 0x70: 1])
        if (cmd) {
            result = zwaveEvent(cmd)
        }
    }
    if (!result) {
        log.debug "Parse returned ${result} for command ${cmd}"
    } else {
        log.debug "Parse returned ${result}"
    }
    return result
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
    dimmerEvents(cmd)
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
    dimmerEvents(cmd)
}

def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelReport cmd) {
    dimmerEvents(cmd)
}

def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelSet cmd) {
    dimmerEvents(cmd)
}

private dimmerEvents(physicalgraph.zwave.Command cmd) {
	def lowThresholdvalue = (settings.lowThreshold != null && settings.lowThreshold != "") ? settings.lowThreshold.toInteger() : 33
	def medThresholdvalue = (settings.medThreshold != null && settings.medThreshold != "") ? settings.medThreshold.toInteger() : 66
	def highThresholdvalue = (settings.highThreshold != null && settings.highThreshold != "") ? settings.highThreshold.toInteger() : 99

    def value = (cmd.value ? "on" : "off")
    def result = [createEvent(name: "switch", value: value)]
    state.lastLevel = cmd.value
    if (cmd.value && cmd.value <= 100) {
        if (cmd.value > 0 && cmd.value <= lowThresholdvalue) { sendEvent(name: "currentState", value: "LOW" as String) }
        if (cmd.value >= lowThresholdvalue+1 && cmd.value <= medThresholdvalue) { sendEvent(name: "currentState", value: "MED" as String) }
	    if (cmd.value >= medThresholdvalue+1) { sendEvent(name: "currentState", value: "HIGH" as String) }
        result << createEvent(name: "level", value: cmd.value, unit: "%")
    }
    return result
}

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

def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) {
    createEvent([name: "hail", value: "hail", descriptionText: "Switch button was pressed", displayed: false])
}

def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
    log.debug "manufacturerId: ${cmd.manufacturerId}"
    log.debug "manufacturerName: ${cmd.manufacturerName}"
    state.manufacturer = cmd.manufacturerName
    log.debug "productId: ${cmd.productId}"
    log.debug "productTypeId: ${cmd.productTypeId}"
    def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
    updateDataValue("MSR", msr)
    setFirmwareVersion()
    createEvent([descriptionText: "$device.displayName MSR: $msr", isStateChange: false])
}

def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) {
    //updateDataValue(“applicationVersion”, "${cmd.applicationVersion}")
    log.debug("received Version Report")
    log.debug "applicationVersion: ${cmd.applicationVersion}"
    log.debug "applicationSubVersion: ${cmd.applicationSubVersion}"
    state.firmwareVersion = cmd.applicationVersion + '.' + cmd.applicationSubVersion
    log.debug "zWaveLibraryType: ${cmd.zWaveLibraryType}"
    log.debug "zWaveProtocolVersion: ${cmd.zWaveProtocolVersion}"
    log.debug "zWaveProtocolSubVersion: ${cmd.zWaveProtocolSubVersion}"
    setFirmwareVersion()
    createEvent([descriptionText: "Firmware V" + state.firmwareVersion, isStateChange: false])
}

def zwaveEvent(physicalgraph.zwave.commands.firmwareupdatemdv2.FirmwareMdReport cmd) {
    log.debug("received Firmware Report")
    log.debug "checksum: ${cmd.checksum}"
    log.debug "firmwareId: ${cmd.firmwareId}"
    log.debug "manufacturerId: ${cmd.manufacturerId}" [: ]
}

def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelStopLevelChange cmd) {
    [createEvent(name: "switch", value: "on"), response(zwave.switchMultilevelV1.switchMultilevelGet().format())]
}

def zwaveEvent(physicalgraph.zwave.Command cmd) {
    // Handles all Z-Wave commands we aren’t interested in
    [:]
}

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

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

def setLevel(value) {
    log.debug "setLevel >> value: $value"
    
    def lowThresholdvalue = (settings.lowThreshold != null && settings.lowThreshold != "") ? settings.lowThreshold.toInteger() : 33
	def medThresholdvalue = (settings.medThreshold != null && settings.medThreshold != "") ? settings.medThreshold.toInteger() : 66
	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 valueaux = value as Integer
    def level = Math.max(Math.min(valueaux, 99), 0)

 	if (level > 0) {
		sendEvent(name: "switch", value: "on")
	} else {
		sendEvent(name: "switch", value: "off")
	}
    
    if (level <= lowThresholdvalue) { sendEvent(name: "currentState", value: "ADJUSTING.LOW" as String, displayed: false) }
	if (level >= lowThresholdvalue+1 && level <= medThresholdvalue) { sendEvent(name: "currentState", value: "ADJUSTING.MED" as String, displayed: false) }
	if (level >= medThresholdvalue+1) { sendEvent(name: "currentState", value: "ADJUSTING.HIGH" as String, displayed: false) }
    
    sendEvent(name: "level", value: level, unit: "%")
    def result = []

    result += response(zwave.basicV1.basicSet(value: level))
    result += response("delay 5000")
    result += response(zwave.switchMultilevelV1.switchMultilevelGet())
    result += response("delay 5000")
    result += response(zwave.switchMultilevelV1.switchMultilevelGet())

}

def lowSpeed() {
	setLevel("LOW")
}

def medSpeed() {
	setLevel("MED")
}

def highSpeed() {
	setLevel("HIGH")
}

/*
 *  Set dimmer to status mode, then set the color of the individual LED
 *
 *  led = 1-7
 *  color = 0=0ff
 *          1=red
 *          2=green
 *          3=blue
 *          4=magenta
 *          5=yellow
 *          6=cyan
 *          7=white
 */

def setBlinkDurationMilliseconds(newBlinkDuration) {
    def cmds = []
    if (0 < newBlinkDuration && newBlinkDuration < 25500) {
        log.debug "setting blink duration to: ${newBlinkDuration} ms"
        state.blinkDuration = newBlinkDuration.toInteger() / 100
        log.debug "blink duration config parameter 30 is: ${state.blinkDuration}"
        cmds << zwave.configurationV2.configurationSet(configurationValue: [state.blinkDuration.toInteger()], parameterNumber: 30, size: 1).format()
    } else {
        log.debug "commanded blink duration ${newBlinkDuration} is outside range 0 … 25500 ms"
    }
    return cmds
}

def setStatusLed(led, color, blink) {
    def cmds = []

    if (state.statusled1 == null) {
        state.statusled1 = 0
        state.statusled2 = 0
        state.statusled3 = 0
        state.statusled4 = 0
        state.blinkval = 0
    }

    /* set led # and color */
    switch (led) {
        case 1:
            state.statusled1 = color
            break
        case 2:
            state.statusled2 = color
            break
        case 3:
            state.statusled3 = color
            break
        case 4:
            state.statusled4 = color
            break
        case 0:
        case 5:
            // Special case - all LED's
            state.statusled1 = color
            state.statusled2 = color
            state.statusled3 = color
            state.statusled4 = color
            break

    }

    if (state.statusled1 == 0 && state.statusled2 == 0 && state.statusled3 == 0 && state.statusled4 == 0 && state.statusled5 == 0 && state.statusled6 == 0 && state.statusled7 == 0) {
        // no LEDS are set, put back to NORMAL mode
        cmds << zwave.configurationV2.configurationSet(configurationValue: [0], parameterNumber: 13, size: 1).format()
    } else {
        // at least one LED is set, put to status mode
        cmds << zwave.configurationV2.configurationSet(configurationValue: [1], parameterNumber: 13, size: 1).format()
    }

    if (led == 5 | led == 0) {
        for (def ledToChange = 1; ledToChange <= 4; ledToChange++) {
            // set color for all LEDs
            cmds << zwave.configurationV2.configurationSet(configurationValue: [color], parameterNumber: ledToChange + 20, size: 1).format()
        }
    } else {
        // set color for specified LED
        cmds << zwave.configurationV2.configurationSet(configurationValue: [color], parameterNumber: led + 20, size: 1).format()
    }

    // check if LED should be blinking
    def blinkval = state.blinkval

    if (blink) {
        switch (led) {
            case 1:
                blinkval = blinkval | 0x1
                break
            case 2:
                blinkval = blinkval | 0x2
                break
            case 3:
                blinkval = blinkval | 0x4
                break
            case 4:
                blinkval = blinkval | 0x8
                break
            case 0:
            case 5:
                blinkval = 0x7F
                break
        }
        cmds << zwave.configurationV2.configurationSet(configurationValue: [blinkval], parameterNumber: 31, size: 1).format()
        state.blinkval = blinkval
        // set blink frequency if not already set, 5=500ms
        if (state.blinkDuration == null | state.blinkDuration < 0 | state.blinkDuration > 255) {
            cmds << zwave.configurationV2.configurationSet(configurationValue: [5], parameterNumber: 30, size: 1).format()
        }
    } else {

        switch (led) {
            case 1:
                blinkval = blinkval & 0xFE
                break
            case 2:
                blinkval = blinkval & 0xFD
                break
            case 3:
                blinkval = blinkval & 0xFB
                break
            case 4:
                blinkval = blinkval & 0xF7
                break
            case 0:
            case 5:
                blinkval = 0
                break
        }
        cmds << zwave.configurationV2.configurationSet(configurationValue: [blinkval], parameterNumber: 31, size: 1).format()
        state.blinkval = blinkval
    }
    delayBetween(cmds, 150)

}

/*
 * Set Dimmer to Status mode (exit normal mode)
 *
 */
 
def setSwitchModeNormal() {
    def cmds = []
    cmds << zwave.configurationV2.configurationSet(configurationValue: [0], parameterNumber: 13, size: 1).format()
    delayBetween(cmds, 500)
}

/*
 * Set the color of the LEDS for normal dimming mode, shows the current dim level
 */
def setSwitchModeStatus() {
    def cmds = []
    cmds << zwave.configurationV2.configurationSet(configurationValue: [1], parameterNumber: 13, size: 1).format()
    delayBetween(cmds, 500)
}

/*
 *   Set the color of the LEDS for normal fan speed mode, shows the current speed
 */

def setDefaultColor(color) {
    def cmds = []
    cmds << zwave.configurationV2.configurationSet(configurationValue: [color], parameterNumber: 14, size: 1).format()
    delayBetween(cmds, 500)
}

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

def refresh() {
    log.debug "refresh() called"
    configure()
}

def zwaveEvent(physicalgraph.zwave.commands.centralscenev1.CentralSceneNotification cmd) {
    log.debug("sceneNumber: ${cmd.sceneNumber} keyAttributes: ${cmd.keyAttributes}")
    def result = []

    switch (cmd.sceneNumber) {
        case 1:
            // Up
            switch (cmd.keyAttributes) {
                case 0:
                    // Press Once
                    result += createEvent(tapUp1Response("physical"))
                    result += createEvent([name: "switch", value: "on", type: "physical"])

                    if (singleTapToFullSpeed) {
                        result += setLevel(99)
                        result += response("delay 5000")
                        result += response(zwave.switchMultilevelV1.switchMultilevelGet())
                    }
                    break
                case 1:
                    result = createEvent([name: "switch", value: "on", type: "physical"])
                    break
                case 2:
                    // Hold
                    result += createEvent(holdUpResponse("physical"))
                    result += createEvent([name: "switch", value: "on", type: "physical"])
                    break
                case 3:
                    // 2 Times
                    result += createEvent(tapUp2Response("physical"))
                    if (doubleTapToFullSpeed) {
                        result += setLevel(99)
                        result += response("delay 5000")
                        result += response(zwave.switchMultilevelV1.switchMultilevelGet())
                    }
                    break
                case 4:
                    // 3 times
                    result = createEvent(tapUp3Response("physical"))
                    break
                case 5:
                    // 4 times
                    result = createEvent(tapUp4Response("physical"))
                    break
                case 6:
                    // 5 times
                    result = createEvent(tapUp5Response("physical"))
                    break
                default:
                    log.debug("unexpected up press keyAttribute: $cmd.keyAttributes")
            }
            break

        case 2:
            // Down
            switch (cmd.keyAttributes) {
                case 0:
                    // Press Once
                    result += createEvent(tapDown1Response("physical"))
                    result += createEvent([name: "switch", value: "off", type: "physical"])
                    break
                case 1:
                    result = createEvent([name: "switch", value: "off", type: "physical"])
                    break
                case 2:
                    // Hold
                    result += createEvent(holdDownResponse("physical"))
                    result += createEvent([name: "switch", value: "off", type: "physical"])
                    break
                case 3:
                    // 2 Times
                    result += createEvent(tapDown2Response("physical"))
                    if (doubleTapDownToDim) {
                        result += setLevel(25)
                        result += response("delay 5000")
                        result += response(zwave.switchMultilevelV1.switchMultilevelGet())
                    }
                    break
                case 4:
                    // 3 Times
                    result = createEvent(tapDown3Response("physical"))
                    break
                case 5:
                    // 4 Times
                    result = createEvent(tapDown4Response("physical"))
                    break
                case 6:
                    // 5 Times
                    result = createEvent(tapDown5Response("physical"))
                    break
                default:
                    log.debug("unexpected down press keyAttribute: $cmd.keyAttributes")
            }
            break

        default:
            // unexpected case
            log.debug("unexpected scene: $cmd.sceneNumber")

    }
    return result
}

def tapUp1Response(String buttonType) {
    sendEvent(name: "status", value: "Tap ▲")
    [name: "button", value: "pushed", data: [buttonNumber: "7"], descriptionText: "$device.displayName Tap-Up-1 (button 7) pressed",
        isStateChange: true, type: "$buttonType"]
}

def tapDown1Response(String buttonType) {
    sendEvent(name: "status", value: "Tap ▼")
    [name: "button", value: "pushed", data: [buttonNumber: "8"], descriptionText: "$device.displayName Tap-Down-1 (button 8) pressed",
        isStateChange: true, type: "$buttonType"]
}

def tapUp2Response(String buttonType) {
    sendEvent(name: "status", value: "Tap ▲▲")
    [name: "button", value: "pushed", data: [buttonNumber: "1"], descriptionText: "$device.displayName Tap-Up-2 (button 1) pressed",
        isStateChange: true, type: "$buttonType"]
}

def tapDown2Response(String buttonType) {
    sendEvent(name: "status", value: "Tap ▼▼")
    [name: "button", value: "pushed", data: [buttonNumber: "2"], descriptionText: "$device.displayName Tap-Down-2 (button 2) pressed",
        isStateChange: true, type: "$buttonType"]
}

def tapUp3Response(String buttonType) {
    sendEvent(name: "status", value: "Tap ▲▲▲")
    [name: "button", value: "pushed", data: [buttonNumber: "3"], descriptionText: "$device.displayName Tap-Up-3 (button 3) pressed",
        isStateChange: true, type: "$buttonType"]
}

def tapUp4Response(String buttonType) {
    sendEvent(name: "status", value: "Tap ▲▲▲▲")
    [name: "button", value: "pushed", data: [buttonNumber: "9"], descriptionText: "$device.displayName Tap-Up-4 (button 9) pressed",
        isStateChange: true, type: "$buttonType"]
}

def tapUp5Response(String buttonType) {
    sendEvent(name: "status", value: "Tap ▲▲▲▲▲")
    [name: "button", value: "pushed", data: [buttonNumber: "11"], descriptionText: "$device.displayName Tap-Up-5 (button 11) pressed",
        isStateChange: true, type: "$buttonType"]
}

def tapDown3Response(String buttonType) {
    sendEvent(name: "status", value: "Tap ▼▼▼")
    [name: "button", value: "pushed", data: [buttonNumber: "4"], descriptionText: "$device.displayName Tap-Down-3 (button 4) pressed",
        isStateChange: true, type: "$buttonType"]
}

def tapDown4Response(String buttonType) {
    sendEvent(name: "status", value: "Tap ▼▼▼▼")
    [name: "button", value: "pushed", data: [buttonNumber: "10"], descriptionText: "$device.displayName Tap-Down-3 (button 10) pressed",
        isStateChange: true, type: "$buttonType"]
}

def tapDown5Response(String buttonType) {
    sendEvent(name: "status", value: "Tap ▼▼▼▼▼")
    [name: "button", value: "pushed", data: [buttonNumber: "12"], descriptionText: "$device.displayName Tap-Down-3 (button 12) pressed",
        isStateChange: true, type: "$buttonType"]
}

def holdUpResponse(String buttonType) {
    sendEvent(name: "status", value: "Hold ▲")
    [name: "button", value: "pushed", data: [buttonNumber: "5"], descriptionText: "$device.displayName Hold-Up (button 5) pressed",
        isStateChange: true, type: "$buttonType"]
}

def holdDownResponse(String buttonType) {
    sendEvent(name: "status", value: "Hold ▼")
    [name: "button", value: "pushed", data: [buttonNumber: "6"], descriptionText: "$device.displayName Hold-Down (button 6) pressed",
        isStateChange: true, type: "$buttonType"]
}

def tapUp1() {
    sendEvent(tapUp1Response("digital"))
}

def tapDown1() {
    sendEvent(tapDown1Response("digital"))
}

def tapUp2() {
    sendEvent(tapUp2Response("digital"))
}

def tapDown2() {
    sendEvent(tapDown2Response("digital"))
}

def tapUp3() {
    sendEvent(tapUp3Response("digital"))
}

def tapDown3() {
    sendEvent(tapDown3Response("digital"))
}

def tapUp4() {
    sendEvent(tapUp4Response("digital"))
}

def tapDown4() {
    sendEvent(tapDown4Response("digital"))
}

def tapUp5() {
    sendEvent(tapUp5Response("digital"))
}

def tapDown5() {
    sendEvent(tapDown5Response("digital"))
}

def holdUp() {
    sendEvent(holdUpResponse("digital"))
}

def holdDown() {
    sendEvent(holdDownResponse("digital"))
}

def setFirmwareVersion() {
    def versionInfo = ''
    if (state.manufacturer) {
        versionInfo = state.manufacturer + ' '
    }
    if (state.firmwareVersion) {
        versionInfo = versionInfo + "Firmware V" + state.firmwareVersion
    } else {
        versionInfo = versionInfo + "Firmware unknown"
    }
    sendEvent(name: "firmwareVersion", value: versionInfo, isStateChange: true, displayed: false)
}

def configure() {
    log.debug("configure() called")

    sendEvent(name: "numberOfButtons", value: 12, displayed: false)
    def commands = []
    commands << setPrefs()
    commands << zwave.switchMultilevelV1.switchMultilevelGet().format()
    commands << zwave.manufacturerSpecificV1.manufacturerSpecificGet().format()
    commands << zwave.versionV1.versionGet().format()
    delayBetween(commands, 500)
}

def setPrefs() {
    log.debug("set prefs")
    def cmds = []

    if (color) {
        switch (color) {
            case "White":
                cmds << zwave.configurationV2.configurationSet(configurationValue: [0], parameterNumber: 14, size: 1).format()
                break
            case "Red":
                cmds << zwave.configurationV2.configurationSet(configurationValue: [1], parameterNumber: 14, size: 1).format()
                break
            case "Green":
                cmds << zwave.configurationV2.configurationSet(configurationValue: [2], parameterNumber: 14, size: 1).format()
                break
            case "Blue":
                cmds << zwave.configurationV2.configurationSet(configurationValue: [3], parameterNumber: 14, size: 1).format()
                break
            case "Magenta":
                cmds << zwave.configurationV2.configurationSet(configurationValue: [4], parameterNumber: 14, size: 1).format()
                break
            case "Yellow":
                cmds << zwave.configurationV2.configurationSet(configurationValue: [5], parameterNumber: 14, size: 1).format()
                break
            case "Cyan":
                cmds << zwave.configurationV2.configurationSet(configurationValue: [6], parameterNumber: 14, size: 1).format()
                break
        }
    }

    if (reverseSwitch) {
        cmds << zwave.configurationV2.configurationSet(configurationValue: [1], parameterNumber: 4, size: 1).format()
    } else {
        cmds << zwave.configurationV2.configurationSet(configurationValue: [0], parameterNumber: 4, size: 1).format()
    }

    if (bottomled) {
        cmds << zwave.configurationV2.configurationSet(configurationValue: [0], parameterNumber: 3, size: 1).format()
    } else {
        cmds << zwave.configurationV2.configurationSet(configurationValue: [1], parameterNumber: 3, size: 1).format()
    }

    //Sets fan type
    if (enable4FanSpeeds) {
        //3 Speeds
        cmds << zwave.configurationV2.configurationSet(configurationValue: [1], parameterNumber: 5, size: 1).format()
    } else {
        //4 Speeds
        cmds << zwave.configurationV2.configurationSet(configurationValue: [0], parameterNumber: 5, size: 1).format()
    }

    //Enable the following configuration gets to verify configuration in the logs
    //cmds << zwave.configurationV1.configurationGet(parameterNumber: 5).format()
    //cmds << zwave.configurationV1.configurationGet(parameterNumber: 7).format()
    //cmds << zwave.configurationV1.configurationGet(parameterNumber: 8).format()
    //cmds << zwave.configurationV1.configurationGet(parameterNumber: 9).format()
    //cmds << zwave.configurationV1.configurationGet(parameterNumber: 10).format()

    return cmds
}

def updated() {
    def cmds = []
    cmds << setPrefs
    delayBetween(cmds, 500)
}