Ikea Blinds

I got 3 blinds all mounted and set up due to the great info in this thread.

In the package:
1 shade
2 mounting brackets
1 battery pack
1 USB A > Micro USB cable
1 Tradfri repeater - Zigbee
1 Remote Button - Zigbee

There are no screws in the package for the mounting brackets. You need 4 screws for each set of shades as there are 2 brackets each.

Step 1 - charge the battery pack. It’s 2,600 MAh and reports I’ve read state it should ‘last several months on a charge’.

Step 2 - Pair the Tradfri repeater in an outlet relatively close to the shade. To pair: Plug in the repeater into the USB plug and then into your outlet. The light will come on steady. To get it in pairing mode, with the repeater plugged in, use a safety-pin/sewing needle and insert it into the small hole next to the USB socket, you will feel the reset button and hold that down with the pin for 10-15 seconds. Remove the pin/needle and the white LED should start to blink. Then set your Hub to Zigbee discovery.

Step 3 - Mount/install the shade hardware - pretty basic and quick

Step 4 - Insert the battery pack into the blinds. There are two small buttons to the left of the battery door that manually operate the shade up and down.

Step 5 - Install the User Driver from @Ryan780 (thank you @Ryan780 ! ) which can be copied from this post (updated to version with battery reporting): Ikea Blinds - #120 by Ryan780

Step 6 - Pair the shade by following @Kev ‘s post quoted here. Remember to use the driver from step 5. After the LED on the blind turns on, set your Hub to Zigbee Pairing mode.

Step 7 - Set the Max Open and close states for the shade. Get the shade where you want it to be ‘most Open’ either via the manual buttons next to the battery or by using Hubitat device page/dashboard. Then double-tap the down button on the shade to the left of the battery pack. The shade will move up and down 1 CM if it was set properly. This now is equal to ‘100’ open for the shade.

So far I’m really pleased and these have boosted the WAF in our home!

11 Likes

It’s all about that Wife Acceptance Factor! lol

I’ve got the three measurements I need, heading to my local location in the morning. Looks like I’ll need to hack off an inch from each one (46.75” is my office window, bedroom windows are 22.75”)

3 Likes

@morningz

2 Likes

Yup! Watched that the other day, thanks!

1 Like

Our household has been really enjoying the Ikea shades so far!

It looks like the creator of the SmartThings driver added the ability to see battery percentage. I tried to port this over to the Hubitat driver and failed spectacularly because I'm not a developer. :slight_smile:

Are there any kind developers out there who would be willing to help me make two modifications to this Hubitat driver?

  1. Add battery percentage to the Hubitat driver - as you can see in the Smart Things driver: https://raw.githubusercontent.com/a4refillpad/Ikea/master/devicetypes/IKEA-window-blinds

  2. Add the ability to turn off debug logging, as these blinds are pretty chatty in the logs (battery level is more important to me, however)

Thank you very much to anyone who even considers this on my behalf!

5 Likes

Try this driver. All I did was add the battery %. I didn't go back through to make make any of the other changes. I did confirm it compiles in Hubitat but since I don't have the blinds, I can't test it.

/**
 *
 *
 *	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.
 *
 *  
 *  first release for IKEA smart window blinds for hubitat adapted from the driver for ST by Wayne Man
 */
import hubitat.zigbee.zcl.DataType

metadata {
    definition(name: "IKEA Window Blinds", namespace: "ryan780", author: "ryan780", ocfDeviceType: "oic.d.blind", mnmn: "SmartThings", vid: "generic-shade") {
        capability "Actuator"
        capability "Configuration"
        capability "Refresh"
        capability "Window Shade"
        capability "Health Check"
        capability "Switch Level"
		capability "Battery"					

        command "pause"
        
       	attribute "lastCheckin", "String"
		attribute "lastOpened", "String"

		fingerprint inClusters: "0000,0001,0003,0004", manufacturer: "IKEA of Sweden", model: "FYRTUR block-out roller blind"
    }
}

private getCLUSTER_BATTERY_LEVEL() { 0x0001 }
private getCLUSTER_WINDOW_COVERING() { 0x0102 }
private getCOMMAND_OPEN() { 0x00 }
private getCOMMAND_CLOSE() { 0x01 }
private getCOMMAND_PAUSE() { 0x02 }
private getCOMMAND_GOTO_LIFT_PERCENTAGE() { 0x05 }
private getATTRIBUTE_POSITION_LIFT() { 0x0008 }
private getATTRIBUTE_CURRENT_LEVEL() { 0x0000 }
private getCOMMAND_MOVE_LEVEL_ONOFF() { 0x04 }

private List<Map> collectAttributes(Map descMap) {
	List<Map> descMaps = new ArrayList<Map>()

	descMaps.add(descMap)

	if (descMap.additionalAttrs) {
		descMaps.addAll(descMap.additionalAttrs)
	}

	return descMaps
}

// Parse incoming device messages to generate events
def parse(String description) {
    log.debug "description:- ${description}"
    def now = new Date().format("yyyy MMM dd EEE h:mm:ss a", location.timeZone)
    //  send event for heartbeat    
    sendEvent(name: "lastCheckin", value: now)
    if (description?.startsWith("read attr -")) {
        Map descMap = zigbee.parseDescriptionAsMap(description)
        if (supportsLiftPercentage() && descMap?.clusterInt == CLUSTER_WINDOW_COVERING && descMap.value) {
            log.debug "attr: ${descMap?.attrInt}, value: ${descMap?.value}, descValue: ${Integer.parseInt(descMap.value, 16)}, ${device.getDataValue("model")}"
            List<Map> descMaps = collectAttributes(descMap)
            def liftmap = descMaps.find { it.attrInt == ATTRIBUTE_POSITION_LIFT }
            if (liftmap && liftmap.value) {
                def newLevel = zigbee.convertHexToInt(liftmap.value)
                levelEventHandler(newLevel)
            }
        } else if (!supportsLiftPercentage() && descMap?.clusterInt == zigbee.LEVEL_CONTROL_CLUSTER && descMap.value) {
            def valueInt = Math.round((zigbee.convertHexToInt(descMap.value)) / 255 * 100)

            levelEventHandler(valueInt)
        }
		if (descMap?.clusterInt == CLUSTER_BATTERY_LEVEL && descMap.value) {
            log.debug "attr: ${descMap?.attrInt}, value: ${descMap?.value}, descValue: ${Integer.parseInt(descMap.value, 16)}"
            sendEvent(name: "battery", value: Integer.parseInt(descMap.value, 16))
        }
    }
}

def levelEventHandler(currentLevel) {
    def lastLevel = device.currentValue("level")
    log.debug "levelEventHandle - currentLevel: ${currentLevel} lastLevel: ${lastLevel}"
    if (lastLevel == "undefined" || currentLevel == lastLevel) { //Ignore invalid reports
        log.debug "Ignore invalid reports"
    } else {
        sendEvent(name: "level", value: currentLevel)
        if (currentLevel == 0 || currentLevel == 100) {
            sendEvent(name: "windowShade", value: currentLevel == 0 ? "open" : "closed")
        } else {
            if (lastLevel < currentLevel) {
																 
												  
                sendEvent([name:"windowShade", value: "closing"])
            } else if (lastLevel > currentLevel) {
                sendEvent([name:"windowShade", value: "opening"])
            }
            runIn(1, "updateFinalState", [overwrite:true])
        }
    }
												  
}

def updateFinalState() {
    def level = device.currentValue("level")
    log.debug "updateFinalState: ${level}"
    if (level > 0 && level < 100) {
        sendEvent(name: "windowShade", value: "partially open")
    }
}

def supportsLiftPercentage() {
    device.getDataValue("manufacturer") != "Feibit Co.Ltd"
}

def close() {
    log.info "close()"
    zigbee.command(CLUSTER_WINDOW_COVERING, COMMAND_CLOSE)

}

def open() {
    log.info "open()"
    zigbee.command(CLUSTER_WINDOW_COVERING, COMMAND_OPEN)
}

def setLevel(data, rate = null) {
						   
    log.info "setLevel()"
    def cmd
	data = data.toInteger()
    if (supportsLiftPercentage()) {
        cmd = zigbee.command(CLUSTER_WINDOW_COVERING, COMMAND_GOTO_LIFT_PERCENTAGE, zigbee.convertToHexString(data, 2))
    } else {
        cmd = zigbee.command(zigbee.LEVEL_CONTROL_CLUSTER, COMMAND_MOVE_LEVEL_ONOFF, zigbee.convertToHexString(Math.round(data * 255 / 100), 2))
    }

    return cmd
}

def pause() {
    log.info "pause()"
    zigbee.command(CLUSTER_WINDOW_COVERING, COMMAND_PAUSE)
}

/**
 * PING is used by Device-Watch in attempt to reach the Device
 * */

def ping() {
       return zigbee.readAttribute(CLUSTER_BATTERY_LEVEL, 0x0021) // Read the Battery Level
}

def refresh() {
    log.info "refresh()"
	
    def cmds
    if (supportsLiftPercentage()) {
        cmds = zigbee.readAttribute(CLUSTER_WINDOW_COVERING, ATTRIBUTE_POSITION_LIFT)
    } else {
        cmds = zigbee.readAttribute(zigbee.LEVEL_CONTROL_CLUSTER, ATTRIBUTE_CURRENT_LEVEL)
    }
    return cmds
}

def configure() {
    // Device-Watch allows 2 check-in misses from device + ping (plus 2 min lag time)
    log.info "configure()"
    sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
    log.debug "Configuring Reporting and Bindings."

    def cmds
    if (supportsLiftPercentage()) {
        cmds = zigbee.configureReporting(CLUSTER_WINDOW_COVERING, ATTRIBUTE_POSITION_LIFT, DataType.UINT8, 0, 600, null)
    } else {
        cmds = zigbee.levelConfig()
    }
    return refresh() + cmds
}

def setPosition(value){
	setLevel(value)
}
5 Likes

Thank you! I will try a bit later today when I’m at a PC. I tried on mobile and the driver functioned (blinds operated the same as before), with no errors in the log. But I’m not seeing any battery info in the logs, on the device page, or on a dashboard where I added the shade as a battery device.

It’s most likely user error on my part, made worse by trying to do this on mobile, so I’ll try again a bit later.

Thank you, again! I very much appreciate your time and effort on this!

I can't stress enough how much I appreciate your efforts.

Unfortunately the battery level doesn't appear to be displayed in Hubitat.

  • I added the driver
  • loaded the driver on the device page
  • hit configure
  • I don't see any errors in the logs.

I have a feeling that it's able to grab the battery level, but it's not displaying that level for some reason. This is an uneducated guess, however.

  • 'Battery level' does not on the device page as an attribute (see attached screenshots for what does display on the device page).
  • It doesn't show up in RM4 or in dashboard as an attribute.
  • Adding a battery tile to dashboard for the shade just shows "???"

If there's anything else I can do to help you debug, please let me know. I am very much aware that you don't have the shades to test with, and you have been volunteering your time thus far which I am grateful for.

Thank you, again!

Genius. I just wish those Farter Blinds came in different colors...

I've just tried @Ryan780 updated driver, the battery level seems to work for me.

Many thanks again :+1:

3 Likes

Oooh! Nice! I’ll try unpairing and repairing the blinds to see if I can get the battery level to work for me.

They’re noisy too :wink: at unexpected times. Blame the dog.

2 Likes

Seriously. Are they really noisy and not in the “blame the dog” sort of way which I’ve been known for? Not sure if the wife would go for that...

I got the drivers to work and was able to use Hubitat to close and open the blinds. I also got the remote it came with to pair but, no drivers. Does anyone have drivers for the remote itself?

Has anyone also gotten this added to Google Home. When setting up Hubitat it only sees my light switches and not these shades.

Not that I’m aware of, at least with Hubitat. But any standard Zigbee/zwave remote could be swapped out to control them through Hubitat.

I got it sorted - thank you again!

If you already have the shades, and are upgrading to the new driver with the battery display, here's how to get it:

  1. Upload the new driver to HE (duh :slight_smile: )
  2. Set the new driver for your shades
  3. From the device page - first hit configre - THEN hit "ping"

Thank you, again @Ryan780

1 Like

Hey...brand new hubitat user here, attacking the IKEA blinds as my first devices (which went extremely smoothly thanks to this thread!), but I have two questions that may be beginner questions:

  1. What happens when the blinds run out of battery.. do they lose their 'maximum length' settings?
  2. How complex is it to integrate user drivers into Google Home to get voice control?
  • What happens when the battery runs out? Nothing other than the blinds simply stop functioning until the battery is recharged. You have to remove the battery to charge it. The blinds retain the memory of their 'maximum length' when the battery is unplugged.

  • How do I get these running on Google Home/Alexa with voice control? There may be easier ways to do it, but here's what I did:

  1. Create a virtual switch in Hubitat called "-whatever you want- Shades" (Mine are "Living Room Shades" for example)
  2. Create a rule in Hubitat.
  • Trigger "When Living Room Shades (changes)"
  • Conditions "Living Room Shades is ON" and "Living Room Shades is OFF"
  • Conditional Rule:
    IF living room shades SWITCH is ON THEN open Living Room Shades.
    ELSE IF living room shades SWITCH is OFF - THEN close Living Room Shades
    END-IF
  1. Then I add the Living Room Shades virtual switch to Alexa as a switch through the HE Alexa App. My voice command is then "Alexa - Turn On Living Room Shades" to open or "Alexa - Turn Off Living Room Shades" to close, which triggers the rule above.

When I explained to my spouse to think of the shades like a light-switch, she understood immediately, and the WAF has gone up substantially since these shades were installed and hooked up with Alexa.

Note: The way I described above opens/closes the shades to 0% or 100%. I can't tell Alexa "Open shades to 30%". I suppose one could create a rule with a virtual dimmer that might be a bit more complex. For times when the sun needs to be blocked by closing the shade slightly, we just use the Hubitat app with the shade on a dashboard.

2 Likes

Just a note on this, you don't need the ELSE IF that's just another test you could just use ELSE because a switch is only a two state device so if it's not ON it has to be OFF.

1 Like

When I set it up a virtual shade it came in as a dimmer with a position variable. You have to do some funkiness though as position 0 is open and position 100 is closed so you have to do the position you want to set it as -100 and then get absolute value.

This seems like a lot of work though than to come in to google home as shades which I am sure it supports to an extent as I do see some other threads asking about them and how it comes in as a light switch and Hubitat saying it s a bug. Not sure if I can find that thread again but, I am having that issue as well...

The virtual shades are coming in as a light dimmer instead of a shade so when I turn off the lights it also triggers the shades.