[OBSOLETE] Hue Dimmer Switch (ZHA) (beta) (no hue bridge)

You can get eight buttons in several different devices. With the remotec 90, you have eight buttons each of which can be pressed, double press, or long-hold, so the equivalent of 24 functions in a Z wave device which works very well with smartthings.


So if that’s the main reason you want the hue device, there are a lot of other options that work much more smoothly with smartthings. :sunglasses:

1 Like

I would love one of those but not available in the UK. How much are they there?

Do you mean the 8 button remotec90?

You can’t use one from the US because it’s zwave, and the US and U.K. zwave frequencies are different. (unlike zigbee)

But Remotec does make a U.K. version which is also popular. Vesternet usually has it. It’s typically around £45.

Z-Wave Remotec Scene Master — Vesternet


It has a different name, Remotec Scene Master, but the same DTH works. :sunglasses:

Thank you. ill check it out!!

1 Like

I think im going to get one of these. Can you get all functionality on smartthings ans core ie one, double and long press? Also where did you get those clear sticky labels from? My wife would need them?
Does it respond quickly upon pressing?

Please take detailed discussion of the remotec 90 Scene Master to the following thread. It is offtopic here. Thanks!

[RELEASE] Remotec ZRC-90 Scene Master - Button Device Supporting 24 Unique Button Commands (see post 177 for 2021 app version)

Thank you for sharing your entire piston. That saved me a chunk of time.

isnt this a better way to make the webcore piston instead of a bunch of if statements, works faster for me atleast

1 Like

[edit] Just realized that the info below is mostly relevant if you are using the classic app, with the new app it seems to recognize all the buttons appropriately without renaming them to 1/2/3/4 and then you can also map the ‘held’ command and whatnot! [/edit]

Hi All,
Pretty new to smart things and coming from a Hue only setup I had 2 switches laying around that I wanted to use. Found this script and noticed it all connected just fine and reported things neatly in the app but my log started throwing errors when I actually tried to hook it up with the smart lighting app.

After some digging I noticed it was trying to parse the on/up/down/off as a number, and since I noticed the automation refers to the buttons as numbers I tried to change what was passed on as an event. Long story short this fixed my issue! And it’s now working as intended. Here is the updated DH if anyone is interested. Also thanks a lot to the original creators!

 *  Hue Dimmer Switch
 *  Copyright 2016 Stephen McLaughlin
 *  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.
metadata {
    definition(name: "Hue Dimmer Switch (ZHA)", namespace: "digitalgecko", author: "Stephen McLaughlin") {
        capability "Configuration"
        capability "Battery"
        capability "Refresh"
        capability "Button"
        capability "Sensor"

        fingerprint profileId: "0104", endpointId: "02", application: "02", outClusters: "0019", inClusters: "0000,0001,0003,000F,FC00", manufacturer: "Philips", model: "RWL020", deviceJoinName: "Hue Dimmer Switch (ZHA)"

        attribute "lastAction", "string"

    simulator {
        // TODO: define status and reply messages here

    tiles(scale: 2) {
        // TODO: define your main and details tiles here
        multiAttributeTile(name: "lastAction", type: "generic", width: 6, height: 4) {
            tileAttribute("device.battery", key: "SECONDARY_CONTROL") {
                attributeState "battery", label: '${currentValue}% battery', icon: "st.Outdoor.outdoor3", unit: "", backgroundColors: [
                        [value: 30, color: "#ff0000"],
                        [value: 40, color: "#760000"],
                        [value: 60, color: "#ff9900"],
                        [value: 80, color: "#007600"]
            tileAttribute("device.lastAction", key: "PRIMARY_CONTROL") {
                attributeState "active", label: '${currentValue}', icon: "st.Home.home30"

        //        valueTile("lastAction", "device.lastAction", width: 6, height: 2) {
        //			state("lastAction", label:'${currentValue}')
        //		}

        valueTile("battery2", "device.battery", decoration: "flat", inactiveLabel: false, width: 5, height: 1) {
            state("battery", label: '${currentValue}% battery', unit: "")
        standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 1, height: 1) {
            state "default", label: "", action: "refresh.refresh", icon: "st.secondary.refresh"
        //        standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
        //            state "default", label:"bind", action:"configure"
        //        }


    main "lastAction"
    details(["lastAction", "battery2", "refresh", "configure"])


// parse events into attributes
def parse(String description) {
    def msg = zigbee.parse(description)

    //log.warn msg
    /// Actual code down here
    List map = []
    if (description?.startsWith('catchall:')) {
        map = parseCatchAllMessage(description)

    def result = map ? map : null

    if (description?.startsWith('enroll request')) {
        List cmds = enrollResponse()
        result = cmds?.collect { new physicalgraph.device.HubAction(it) }
    } else if (description?.startsWith('read attr -')) {
        result = parseReportAttributeMessage(description).each { createEvent(it) }

    return result

    // TODO: handle 'numberOfButtons' attribute


private List parseReportAttributeMessage(String description) {
    Map descMap = (description - "read attr - ").split(",").inject([:]) { map, param ->
        def nameAndValue = param.split(":")
        map += [(nameAndValue[0].trim()): nameAndValue[1].trim()]

    List result = []

    // Battery
    if (descMap.cluster == "0001" && descMap.attrId == "0020") {
        // log.warn descMap
        result << getBatteryResult(Integer.parseInt(descMap.value, 16))

    return result

private boolean shouldProcessMessage(cluster) {
    // 0x0B is default response indicating message got through
    boolean ignoredMessage = cluster.profileId != 0x0104 ||
            cluster.command == 0x0B ||
            (cluster.data.size() > 0 && cluster.data.first() == 0x3e)
    return !ignoredMessage

//TODO: needs calibration
private Map getBatteryResult(rawValue) {
    //log.debug "Battery rawValue = ${rawValue}"

    def result = [
            name        : 'battery',
            value       : '--',
            translatable: true

    def volts = rawValue / 10

    if (rawValue == 0 || rawValue == 255) {
    } else {
        if (volts > 3.5) {
            result.descriptionText = "{{ device.displayName }} battery has too much power: (> 3.5) volts."
        } else {
            if (device.getDataValue("manufacturer") == "SmartThings") {
                volts = rawValue // For the batteryMap to work the key needs to be an int
                def batteryMap = [28: 100, 27: 100, 26: 100, 25: 90, 24: 90, 23: 70,
                                  22: 70, 21: 50, 20: 50, 19: 30, 18: 30, 17: 15, 16: 1, 15: 0]
                def minVolts = 15
                def maxVolts = 28

                if (volts < minVolts)
                    volts = minVolts
                else if (volts > maxVolts)
                    volts = maxVolts
                def pct = batteryMap[volts]
                if (pct != null) {
                    result.value = pct
                    result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
            } else {
                def minVolts = 2.1
                def maxVolts = 3.0
                def pct = (volts - minVolts) / (maxVolts - minVolts)
                def roundedPct = Math.round(pct * 100)
                if (roundedPct <= 0)
                    roundedPct = 1
                result.value = Math.min(100, roundedPct)
                result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"

    return result

private List getButtonResult(rawValue) {
    def result
    def button = rawValue[0]
    def buttonState = rawValue[4]
    def buttonHoldTime = rawValue[6]
    def hueStatus = (button as String) + "00" + (buttonState as String)
    // This is the state in the HUE api
    log.error "Button: " + button + "  Hue Code: " + hueStatus + "  Hold Time: " + buttonHoldTime + "  Button State: " + buttonState
    //   result.data = ['buttonNumber': button]

    def buttonName

    // Name of the button
    if (button == 1) {
        buttonName = "1"
    } else if (button == 2) {
        buttonName = "2"
    } else if (button == 3) {
        buttonName = "3"
    } else if (button == 4) {
        buttonName = "4"

    // The button is pressed, aka: pushed + released, with 0 hold time
    if (buttonState == 0) {
        result = [createEvent(name: "button", value: "pressed", data: [buttonNumber: buttonName], descriptionText: "$device.displayName button $button was pushed", isStateChange: true)]
        sendEvent(name: "lastAction", value: buttonName + " pressed")
    // The button is pressed, aka: pushed + released, with at least 1s hold time
    else if (buttonState == 2) {
        result = [
                createEvent(name: "button", value: "pushed", data: [buttonNumber: buttonName], descriptionText: "$device.displayName button $button was pushed", isStateChange: true),
                createEvent(name: "button", value: "released", data: [buttonNumber: buttonName], descriptionText: "$device.displayName button $button was pushed", isStateChange: true)
        sendEvent(name: "lastAction", value: buttonName + " pushed")
        sendEvent(name: "lastAction", value: buttonName + " released")
    // The button is released, with at least 1s hold time. This code happens after the button is held
    else if (buttonState == 3) {
        result = [
                createEvent(name: "button", value: "released", data: [buttonNumber: buttonName], descriptionText: "$device.displayName button $button was pushed", isStateChange: true)
        sendEvent(name: "lastAction", value: buttonName + " released")
    // The button is held
    else if (buttonHoldTime == 8) {
        result = [createEvent(name: "button", value: "held", data: [buttonNumber: buttonName], descriptionText: "$device.displayName button $button was held", isStateChange: true)]
        sendEvent(name: "lastAction", value: buttonName + " held")
    } else {
    return result



private List parseCatchAllMessage(String description) {
    List resultMap = []
    def cluster = zigbee.parse(description)
    if (shouldProcessMessage(cluster)) {
        switch (cluster.clusterId) {
            case 0x0001:
                // 0x07 - configure reporting
                if (cluster.command != 0x07) {
                    resultMap = [getBatteryResult(cluster.data.last())]

            case 0xFC00:
                if (cluster.command == 0x00) {
                    resultMap = getButtonResult(cluster.data);


    return resultMap

def refresh() {
    //log.debug "Refresh"

    def refreshCmds = []

    refreshCmds += "st rattr 0x${device.deviceNetworkId} 0x02 0x0001 0x0020";
    // WORKS! - Fetches battery from 0x02

    //   configCmds += zigbee.configureReporting(0x406,0x0000, 0x18, 30, 600, null) // motion // confirmed

    //refreshCmds += zigbee.configureReporting(0x000F, 0x0055, 0x10, 30, 30, null);
    //	refreshCmds += "zdo bind 0xDAD6 0x01 0x02 0x000F {00178801103317AA} {}"
    //    refreshCmds += "delay 2000"
    //    refreshCmds += "st cr 0xDAD6 0x02 0x000F 0x0055 0x10 0x001E 0x001E {}"
    //    refreshCmds += "delay 2000"

    //refreshCmds += zigbee.configureReporting(0x000F, 0x006F, 0x18, 0x30, 0x30);
    //	refreshCmds += "zdo bind 0x${device.deviceNetworkId} 0x02 0x02 0xFC00 {${device.zigbeeId}} {}"
    //   refreshCmds += "delay 2000"
    //  refreshCmds += "st cr 0x${device.deviceNetworkId} 0x02 0xFC00 0x0000 0x18 0x001E 0x001E {}"
    //  refreshCmds += "delay 2000"
    //log.debug refreshCmds

    return refreshCmds

def configure() {
    //	String zigbeeId = swapEndianHex(device.hub.zigbeeId)
    //log.debug "Configiring Reporting and Bindings."
    def configCmds = []

    // Configure Button Count
    sendEvent(name: "numberOfButtons", value: 4, displayed: false)

    // Monitor Buttons
    //TODO: This could be zigbee.configureReporting(0xFC00, 0x0000, 0x18, 0x001e, 0x001e); but no idea how to point it at a different endpoint
    configCmds += "zdo bind 0x${device.deviceNetworkId} 0x02 0x02 0xFC00 {${device.zigbeeId}} {}"
    configCmds += "delay 2000"
    configCmds += "st cr 0x${device.deviceNetworkId} 0x02 0xFC00 0x0000 0x18 0x001E 0x001E {}"
    configCmds += "delay 2000"

    // Monitor Battery
    //TODO: This could be zigbee.batteryConfig(); but no idea how to point it at a different endpoint
    configCmds += "zdo bind 0x${device.deviceNetworkId} 0x02 0x02 0x0001 {${device.zigbeeId}} {}"
    configCmds += "delay 2000"
    configCmds += "st cr 0x${device.deviceNetworkId} 0x02 0x0001 0x0020 0x20 0x001E 0x0258 {}"
    //    configCmds += "st cr 0x${device.deviceNetworkId} 0x02 0x0001 0x0020 0x20 0x001E 0x001e {}"

    configCmds += "delay 2000"

    return configCmds + refresh()


def configureHealthCheck() {
    Integer hcIntervalMinutes = 12
    sendEvent(name: "checkInterval", value: hcIntervalMinutes * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])

def updated() {
    // log.debug "in updated()"


i just bought the remote and i tried everything

can someone help me please and right the steps by step

Hue released a new firmware for dimmer switches some days ago.
Would there be a benefit in pairing with the hue bridge just to update and then pairing with SmartThings again afterwards?

Hi, finally works of I add directly to something to use it with webcore? Thanks.

If i add it to hue bridge and the bridge to smartthing…can I use the dinner with webcore to do routines?

I have a DTH for Hue Dimmer which has a setting so you can choose to return on,up,down,off or 1,2,3,4

It was designed to work with ABC controller which needs button numbers.

Paulsheldon/ SmartThings-PS

The latest version of ABC controller supporting the Hue button is also in this repositary


Hi. Forgive me if this has been answered but I’m struggling. I have added the Hue Dimmer and it asks me to name it. Then all it does is “please wait” I read that I may need to change the ‘type’ in the IDE which I have but non of the ones I have tried give all the options this DTH should have. Any suggestions?

Anyone have any ideas where I’m going wrong?

I’d like to use this as a regular button without ABC but the device handler by itself doesn’t show button mappings like the SmartThings button or Aeotec or Ikea etc. do

see here:

Sorry to drag up an old thread, I had a few of these dimmers prior to purchasing smartthings, I have read this full thread and a few others regarding this particular dimmer. I managed to get the dimmer switches to pair by changing the model number to in the device handler to ’ RWL021’ I have also set allow unsecure join to true as another member posted in the thread reporting that this should stop it from dropping offline but I dont seem to have the same success no matter what I try.

When paired the dimmer swtich drops offline within 5 minutes within the new smart things app, if you press any button it will flash red, taking the battery out and in seems to bring them back online, you dont need to reset and repair, the odd time if you walk around with the dimmer pressing the buttons it will also come back online by itself.

I was wondering if anyone ever got round the issue with them dropping offline?

I added the device handle from the code, Smartthings detected a Thing which I edited to a Hue Dimmer Switch but that don’t seems to work still (only one button found and not configurable)

I already have one Hue dimmer connected directly to ST hub. But I cannot work out how to add a new one directly to ST in the new app. I seem to only have the option via Brand.
Can someone walk me thru it thanks.

Ahhh manged to add it via the “Scan Nearby” under add device.