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

UPDATE> Got WebCore and Hue Dimmer Switch working.

Leave the DH as is (Do Not Modify). No Need for ABC.
This piston can be modified to allow for LIFX Scenes and Color Change etc. Or any device at actually,

1 Like

This did not work anymore, the event was send but it seemed with the wrong value.
I have fixed it for me. The part from line 207 on is the problem.
The parts with
... value: "pressed_" + buttonName ...
are not working because the value is wrong. It must be
... value: "pressed" ...

Here the whole part:

	// 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

}

Now the data is send in the right way again.

Hi everyone.

any idea why this isn’t working? when it found it, it came up as ‘thing’ but changed it in the IDE. it recognises the presses in the core but it will nlt action. also tried the above but to no avail. help appreciated.

thank you

Sorted! No capitals!!!

Has anyone had any luck keeping these paired. For me it seems to pair for a day or a few hours then drops out; just get the red led then have to re-pair. Any advice and tips greatly appreciated as this is so ideal, essentially 8 buttons in l e device!

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.

image

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.

https://www.vesternet.com/z-wave-remotec-scene-master

image

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

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()
}
1 Like

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?