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

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!

[OBSOLETE] 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

}
/*
parseReportAttributeMessage
 */

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
}

/*
getBatteryResult
 */
//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
    }
    return result

}

/*
parseCatchAllMessage
 */

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())]
                }
                break

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

        }
    }

    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
    refresh()
    sendEvent(name: "checkInterval", value: hcIntervalMinutes * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}

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

    configureHealthCheck()
}
2 Likes

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

2 Likes

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.

My original Hue Dimmer is still working directly with ST.
The two new one I have just added look ok in the app, however, NO Automations, Smart Lighting or ABC do anything at all. I can see the presses in the IDE but the lights or switches dont activate (even the ones that work with the original).
As far as I can tell from the IDE they are set up identically, same device handler, same ABC Smartapp, same dimmer revision.
I must be missing something somewhere.
Any suggestions??

1 Like

I just bought the dimmer as well. What finally made it work for me is to open the dimmer device itself (on the phone app), click the 3 dots in the top right, click ā€œSettingsā€, then turn on the toggle for ā€œButton Names - Use 1,2,3,4ā€.

Hope this fixes it for you as well!

Well - thanks for that, it worked for me also.
The first time I have found settings useful !
Pretty certain didnt do that for the first dimmer I up some time ago.