IKEA Knycklan Water Valve for Dishwashers

Hello all,

IKEA has started to sell a Zigbee water valve designed for dishwashers called Knycklan

Having a dishwater shut-off is an insurance requirement here in Sweden, but my wife often forgets to switch on the water supply. Via IFTTT my dishwasher can tell Hubitat when it starts and ends a cycle, and I would like to open and close the valve automatically.

Although I can get the valve device to pair with Hubitat, but I can't control it - I've tried various device types.

There is a video of this device and its button being added to SmartThings, and I see that this guy is using a "Zigbee Valve" device type. There is no such device type in Hubitat.

Does anyone have any ideas on how to get this device working?

Thanks!

I have a generic shutoff valve, that uses the "generic zigbee switch" driver. If you can get the device to pair as "device", the change the driver to the above, it should work. Just note not all Ikea zigbee devices work outside of their own ikea system

2 Likes

If you don't mind my curiosity.... this valve shows what appears to be an input and output. In addition there is a threaded fitting coming off on an angle. Can you tell us what it is for?

Thanks John

Sorry - my first response was wrong (I was focused on the valve controller and not the valve) and I deleted it.

The manual shows the threaded fitting connecting to a spray hose - perhaps to use in the sink?

The way I read that is the bottom left fitting is inlet, top fitting is outlet to sink, and the right angle fitting is out to dishwasher.

3 Likes

That makes sense.

1 Like

Yes, that's how it's installed. It's a nice little unit, and at €50 I wonder if it could have other applications - watering the garden perhaps!

2 Likes

I agree it makes sense. You wouldn't divert only cold water to the sprayer.

Thank you all for putting up with my curiosity.

John

1 Like

Yup. @neonturbo got that right.

Thanks Rxich
I tried all of the Generic drivers, and all of the IKEA drivers but none worked.
It seemed to work with SmartThings in the video, but perhaps he had an IKEA hub paired with SmartThings? Maybe I could do the same with Hubitat...?

Unfortunately, that's not supported. Perhaps if @mike.maxwell had this device, he may be able to write a Hubitat driver for it - assuming it is compatible (not all Ikea devices are).

On the other hand, thanks to the integrated leak sensor, the device is nicely self-contained, so it can shut the valve if necessary.

Bugger.

Yep - it also shuts off after three hours anyway. The bigger problem is the wife remembering to switch it on, or switching it on if we put the dishwasher on a timer...

@mike.maxwell if the mood takes you to write a driver, I'll ship one of the devices to you :wink:

That is a bizarro design. The top is the sink, the bottom is the inlet. The one off to the right is the dishwasher.

First, why in the heck would you point the Y in that direction?

Second, the device to the right is a valve itself. I don't know about the rest of the dishwashers in Europe, but my Miele dishwasher has a fitting just like that. It's a valve that turns the water supply to the dishwasher on and off right at the source when its needed, thus preventing leaks from burst dishwasher hoses. So what they're suggesting to connect to their electric valve, is an electric valve. :roll_eyes:

1 Like

You can just about see here that the dishwasher feed comes down from the IKEA valve, and goes through the bottom of the under-sink cabinet. Pointing downwards means that this pipe doesn't need to do a 90- or 180-degree bend.

Yes, like your Miele, this appliance also has AquaStop, so you're right - there are two shut off valves! This is all down to Swedish building regulations requiring an off button to the water supply that is above the kitchen worktop. It would be much easier if there were an input into the AquaStop....

3 Likes

What an odd and unnecessary law. Why does that “Aquastop” even need to be manually controlled?

Who knows! Maybe it predates AquaStop, or is just simpler to enforce than "if you don't have AquaStop then you must have a separate shut off".

But none of these things help me get a driver that works :joy:

1 Like

True. Sorry to divert the thread.

Is there any code available from Smartthings that could be modified or is it built-in? I believe much of their built-in code used to be available on a github repo. I don’t know if that’s still the case.

ok, but i'm super backed up on devices currently, but this should be a super simple one

3 Likes

Here @Ement. Zigbee Valve. Try just making the required changes for HE and see if it works.

3 Likes

Try this. I think I didn't screw it up :joy:

/**
 *  Copyright 2016 SmartThings
 *
 *  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.
 *
 */
import hubitat.zigbee.clusters.iaszone.ZoneStatus
import hubitat.zigbee.zcl.DataType

metadata {
    definition (name: "ZigBee Valve", namespace: "smartthings", author: "SmartThings", runLocally: true, minHubCoreVersion: '000.017.0012', executeCommandsLocally: false) {
        capability "Actuator"
        capability "Battery"
        capability "Configuration"
        capability "Power Source"
        capability "Refresh"
        capability "Valve"

        fingerprint profileId: "0104", inClusters: "0000, 0001, 0003, 0006, 0020, 0B02, FC02", outClusters: "0019", manufacturer: "WAXMAN", model: "leakSMART Water Valve v2.10", deviceJoinName: "leakSMART Valve" //leakSMART Valve
        fingerprint profileId: "0104", inClusters: "0000, 0001, 0003, 0004, 0005, 0006, 0008, 000F, 0020, 0B02", outClusters: "0003, 0019", manufacturer: "WAXMAN", model: "House Water Valve - MDL-TBD", deviceJoinName: "Waxman Valve" //Waxman House Water Valve
        fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0006, 0500", outClusters: "0019", manufacturer: "", model: "E253-KR0B0ZX-HA", deviceJoinName: "Valve" //Smart Gas Valve Actuator
    }

}

private getCLUSTER_BASIC() { 0x0000 }
private getBASIC_ATTR_POWER_SOURCE() { 0x0007 }
private getCLUSTER_POWER() { 0x0001 }
private getPOWER_ATTR_BATTERY_PERCENTAGE_REMAINING() { 0x0021 }

// Parse incoming device messages to generate events
def parse(String description) {
    log.debug "description is $description"
    def event = zigbee.getEvent(description)
    if (event) {
        if(event.name == "switch") {
            event.name = "contact"                  //0006 cluster in valve is tied to contact
            if(event.value == "on") {
                event.value = "open"
            }
            else if(event.value == "off") {
                event.value = "closed"
            }
            sendEvent(event)
            // we need a valve and a contact event every time
            event.name = "valve"
        } else if (event.name == "powerSource") {
            event.value = event.value.toLowerCase()
        }
        sendEvent(event)
    }
    else {
        def descMap = zigbee.parseDescriptionAsMap(description)
        if (descMap.clusterInt == CLUSTER_BASIC && descMap.attrInt == BASIC_ATTR_POWER_SOURCE){
            def value = descMap.value
            if (value == "01" || value == "02") {
                sendEvent(name: "powerSource", value: "mains")
            }
            else if (value == "03") {
                sendEvent(name: "powerSource", value: "battery")
            }
            else if (value == "04") {
                sendEvent(name: "powerSource", value: "dc")
            }
            else {
                sendEvent(name: "powerSource", value: "unknown")
            }
        }
        else if (descMap.clusterInt == CLUSTER_POWER && descMap.attrInt == POWER_ATTR_BATTERY_PERCENTAGE_REMAINING) {
            event.name = "battery"
            event.value = Math.round(Integer.parseInt(descMap.value, 16) / 2)
            sendEvent(event)
        }
        else {
            log.warn "DID NOT PARSE MESSAGE for description : $description"
            log.debug descMap
        }
    }
}

def open() {
    zigbee.on()
}

def close() {
    zigbee.off()
}

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

    def cmds = []
    cmds += zigbee.onOffRefresh()
    cmds += zigbee.readAttribute(CLUSTER_BASIC, BASIC_ATTR_POWER_SOURCE)
    cmds += zigbee.readAttribute(CLUSTER_POWER, POWER_ATTR_BATTERY_PERCENTAGE_REMAINING)
    cmds += zigbee.onOffConfig()
    cmds += zigbee.configureReporting(CLUSTER_BASIC, BASIC_ATTR_POWER_SOURCE, DataType.ENUM8, 5, 21600, 1)
    cmds += zigbee.configureReporting(CLUSTER_POWER, POWER_ATTR_BATTERY_PERCENTAGE_REMAINING, DataType.UINT8, 600, 21600, 1)
    return cmds
}

def configure() {
    log.debug "Configuring Reporting and Bindings."
    refresh()
}

def installed() {
    sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"])
}

def ping() {
    zigbee.onOffRefresh()
}
1 Like