Somfy Motorized Blinds (Z-Wave)

Sent a private message.

Everyone, I’ve created a SmartApp and Device Handler that will allow you to control your blinds as a group.

I’ve also created a Device Handler for the Somfy Autoview blinds. Anyone who has the older blinds want to test it out?

2 Likes

@Ash

Have you noticed that “dimming to 50%” lately doesn’t open to the My/Stop position? It works fine when I use my Somfy remote, but for some reason in SmartThings the 50% command only opens slightly then stops. Wondering if anyone else has noticed the same issue? Worked fine for months after initially using the code, but for some reason it seems to have changed…

Am I the only one having this issue? The My/Stop button opens/closes (depending on the current position) about 1", stops, few second delay, moves about 1" again, then stops for good. Does not go to the pre-programmed position…

What dth are your using? I’m not having this problem

DTH is Device Type Handler? I’m using the below that Ash put together:

/**
*

*/
metadata {
definition (name: “Somfy Z-Wave Shades Multi tile”, namespace: “ash”, author: “Ash Raj”) {
capability “Switch Level”
capability “Switch”
capability “Window Shade”
//capability “Polling”
capability “Refresh”
capability “Actuator”

    command "levelOpenClose"
    fingerprint deviceId: "0x1105", inClusters: "0x2C, 0x72, 0x26, 0x20, 0x25, 0x2B, 0x86"
}
simulator {
    status "on":  "command: 2003, payload: FF"
    status "off": "command: 2003, payload: 00"
    status "09%": "command: 2003, payload: 09"
    status "10%": "command: 2003, payload: 0A"
    status "33%": "command: 2003, payload: 21"
    status "66%": "command: 2003, payload: 42"
    status "99%": "command: 2003, payload: 63"
    
    // reply messages
    reply "2001FF,delay 5000,2602": "command: 2603, payload: FF"
    reply "200100,delay 5000,2602": "command: 2603, payload: 00"
    reply "200119,delay 5000,2602": "command: 2603, payload: 19"
    reply "200132,delay 5000,2602": "command: 2603, payload: 32"
    reply "20014B,delay 5000,2602": "command: 2603, payload: 4B"
    reply "200163,delay 5000,2602": "command: 2603, payload: 63"
}
tiles(scale: 2) {
    multiAttributeTile(name:"shade", type: "lighting", width: 6, height: 4) {
        tileAttribute("device.windowShade", key: "PRIMARY_CONTROL") {
            attributeState("unknown", label:'${name}', action:"refresh.refresh", icon:"st.doors.garage.garage-open", backgroundColor:"#ffa81e")
            attributeState("closed", label:'${name}', action:"open", icon:"st.doors.garage.garage-closed", backgroundColor:"#bbbbdd", nextState: "opening")
            attributeState("open", label:'${name}', action:"close", icon:"st.doors.garage.garage-open", backgroundColor:"#ffcc33", nextState: "closing")
            attributeState("partially open", label:'stop/my', action:"presetPosition", icon:"st.doors.garage.garage-open", backgroundColor:"#ffcc33")
            attributeState("closing", label:'${name}', action:"presetPosition", icon:"st.doors.garage.garage-closing", backgroundColor:"#bbbbdd")
            attributeState("opening", label:'${name}', action:"presetPosition", icon:"st.doors.garage.garage-opening", backgroundColor:"#ffcc33")
        }
        tileAttribute ("device.level", key: "SLIDER_CONTROL") {
            attributeState("level", action:"switch level.setLevel")
        }
        tileAttribute ("device.speedLevel", key: "VALUE_CONTROL") {
            attributeState("level", action: "levelOpenClose")
        }
    }
    standardTile("switchmain", "device.switch", width: 2, height: 2) {
        state "on", label:'open', action:"switch.off", icon:"st.doors.garage.garage-open", backgroundColor:"#ffcc33"
        state "off", label:'closed', action:"switch.on", icon:"st.doors.garage.garage-closed", backgroundColor:"#bbbbdd"
        state "default", label:'stop/my', action:"presetPosition", icon:"st.doors.garage.garage-open", backgroundColor:"#ffcc33"
    }
    standardTile("on", "device.switch", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
        state("on", label:'open', action:"switch.on", icon:"st.doors.garage.garage-opening")
    }
    standardTile("off", "device.switch", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
        state("off", label:'close', action:"switch.off", icon:"st.doors.garage.garage-closing")
    }
    standardTile("stop", "device.level", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
        state("default", label:'stop/my', action:"switch level.setLevel", icon:"st.Transportation.transportation13")
    }
    controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 3, inactiveLabel: false) {
        state("level", action:"switch level.setLevel")
    }
    standardTile("refresh", "command.refresh", width:2, height:2, inactiveLabel: false, decoration: "flat") {
            state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
    }

// Poll provides data, but the ZRTSII does not provide accurate status
//
// standardTile(“poll”, “command.poll”, width:2, height:2, inactiveLabel: false, decoration: “flat”) {
// state “default”, label:‘poll’, action:“poll”, icon:“st.secondary.poll”
// }

    main(["switchmain"])
    details(["shade", "on", "off", "stop"])
}

}

def parse(String description) {
description
def result = null
def cmd = zwave.parse(description, [0x20: 1, 0x26: 1, 0x70: 1])
log.debug “Parsed ${description} to ${cmd}”
if (cmd) {
result = zwaveEvent(cmd)
log.debug “zwaveEvent( ${cmd} ) returned ${result.inspect()}”
} else {
log.debug “Non-parsed event: ${description}”
}
return result
}

def levelOpenClose(value) {
log.trace “levelOpenClose called with value $value”
if (value) {
on()
} else {
off()
}
}

// Somfy ZRTSII does not report accurate status for the device.
// This device handler maintains an internal view of device status based on last command
// reissuing a command to the shade (up, down, my (when stopped)) does not move the shade if it is already in that position
// My/stop command does different actions depending if the shade is idle (go to MY position) or moving (stop)

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd)
{
def result =
log.trace “Basic report cmd.value: ${cmd.value}”
if (cmd.value == 0) {
//result << createEvent(name: “switch”, value: “off”)
log.debug "Reported state is closed; device is ${device.latestValue(‘switch’)} ${device.latestValue(‘level’)} "
} else if (cmd.value == 0xFF) {
//result << createEvent(name: “switch”, value: “on”)
log.debug "Reported state is open; device is ${device.latestValue(‘switch’)} ${device.latestValue(‘level’)} "
} else { // This has never happend
//result << createEvent(name: “switch”, value: “default”)
log.debug "Reported state is neither open or closed; device is ${device.latestValue(‘switch’)} ${device.latestValue(‘level’)} "
}
return result
}

def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) {
def result =
log.debug “SwitchBinaryReport cmd.value: ${cmd.value}”

if (cmd.value == 0) {
    log.debug "Reported state is closed; device is ${device.latestValue('switch')}  ${device.latestValue('level')} "
} else if (cmd.value == 0xFF) {
    log.debug "Reported state is open; device is ${device.latestValue('switch')}  ${device.latestValue('level')} "
} else {  // this has never happened
    log.debug "Reported state is neither open or closed; device is ${device.latestValue('switch')}  ${device.latestValue('level')} "
}

//result << createEvent(name:"switch", value: cmd.value ? "on" : "off")
//result << createEvent(name: "level",value: cmd.value, unit:"%",
    //descriptionText:"${device.displayName} dimmed ${cmd.value==255 ? 100 : cmd.value}%")
return result

}

def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelReport cmd)
{
def result =
log.trace “SwitchMultilevelReport cmd.value: ${cmd.value}”

if (cmd.value == 0) {
    //result << createEvent(name: "switch", value: "off")
    log.debug "Reported state is closed; device is ${device.latestValue('switch')}  ${device.latestValue('level')} "
} else if (cmd.value == 0xFF) {
    //result << createEvent(name: "switch", value: "on")
    log.debug "Reported state is open; device is ${device.latestValue('switch')}  ${device.latestValue('level')} "
} else {
   //result << createEvent(name: "switch", value: "default")
   log.debug "Reported state is neither open or closed; device is ${device.latestValue('switch')}  ${device.latestValue('level')} "
}
//result << createEvent(name: "level",value: cmd.value, unit:"%",
  //descriptionText:"${device.displayName} dimmed ${cmd.value==255 ? 100 : cmd.value}%")
return result

}

def on() {
int level = 100
log.trace “on() treated as open()”
setLevel(level)
}

def off() {
int level = 0
log.trace “off() treated as close()”
setLevel(level)
}

def setLevel() {
log.trace “setLevel() treated as my/stop”
setLevel(50)
}

def open() {
log.trace “open()”
on()
}

def close() {
log.trace “close()”
off()
}

def presetPosition() {
log.trace “presetPosition() treated as my/stop”
setLevel()
}

def refresh() {
log.trace “refresh()”
delayBetween([
zwave.switchBinaryV1.switchBinaryGet().format(),
zwave.switchMultilevelV1.switchMultilevelGet().format(),
//zwave.meterV2.meterGet(scale: 0).format(), // get kWh
//zwave.meterV2.meterGet(scale: 2).format(), // get Watts
//zwave.sensorMultilevelV1.sensorMultilevelGet().format(),
//zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType:1, scale:1).format(), // get temp in Fahrenheit
//zwave.batteryV1.batteryGet().format(),
zwave.basicV1.basicGet().format(),
], 3000)
}

// If you add the Polling capability to your device type, this command
// will be called approximately every 5 minutes to check the device’s state
// zrtsII does not provide accurate status of shade position
//def poll() {
// log.trace “Poll”
// zwave.basicV1.basicGet().format()
//}

def setLevel(level) {
log.trace “setLevel(level) {$level}”
log.debug "level.inspect " + level.inspect()

int newlevel = level
if (level > null) {
    sendEvent(name: "level", value: level)
    if (level >= 75) {
        sendEvent(name: "windowShade", value: "opening")
        newlevel = 100
        delayBetween([
            zwave.switchMultilevelV1.switchMultilevelSet(value: 0xFF).format(),
            sendEvent(name: "switch", value: "on"),
            sendEvent(name: "windowShade", value: "open")
        ], 5000)
    } else if (level <= 25) {
        sendEvent(name: "windowShade", value: "closing")
        newlevel = 0
        delayBetween([
            zwave.switchMultilevelV1.switchMultilevelSet(value: 0x00).format(),
            sendEvent(name: "switch", value: "off"),
            sendEvent(name: "windowShade", value: "closed")
        ], 5000)
    } else {
        delayBetween([
            zwave.switchMultilevelV1.switchMultilevelStopLevelChange().format(),
            sendEvent(name: "switch", value: "default"),
            sendEvent(name: "windowShade", value: "partially open")
        ], 5000)
    }
    // this code below causes commands not be sent/received by the Somfy ZRTSII - assume delayBetween is asynchronous...
    //log.trace("finished level adjust")
    //if (newlevel != level) { 
        //log.trace("finished level adjust1")
        //delayBetween([
            //sendEvent(name: "level", value: newlevel)
        //], 1000)
    //}
}

}

// this appears to never be called

//def setLevel(level, duration) {
// log.trace “setLevel(level, duration) {$level} ${duration}”
// setLevel(level)
// return
//}

I suggest you use this one:

https://github.com/imnotbob/SmartThings-1/blob/Develop/somfy_shades.groovy

Thanks for the heads up, Eric. I used that code and it does the same thing unfortunately, so I think it must be something in my ZRTSII module if no one is running into the same issues. Thanks for letting me know it was just me. :slight_smile:

Being my physical remote still worked fine I was thinking maybe something had been adjusted on the SmartThings side. I’ll investigate on my end and post my findings when I get a chance.

I’m interested in ordering the ZRTSII, but I’m a new forum user and I don’t think I’m allowed to PM you.

Lowe’s is running a sale now through 3rd week of November I believe. I ordered two of these for about $76 each. Make sure you have the salesperson order under the Bali accessories, not Graber as the same device listed under Graber is around $100. Also, interestingly enough, Graber owns Bali.

Do you have to go into the store to order the ZRTSI? What do I need to ask for? It seems like an odd product that they will have trouble looking up to order.

Hi Please tell me how can I buy a ZRTSII from you

Sent a PM (10 char)

Matthew, Is this the same RTS interface #1811265, LCD screen model at the automated shade website? Do you have any more available. How do I contact you to purchase one?

Hi, another new forum user here who is interested in buying a ZRTSII from you.

Also a new forum user looking for a zRTSii. Please PM me.

Latest DTH

https://github.com/imnotbob/SmartThings-1/blob/Develop/somfy_shades.groovy

2 Likes

Anyone had any luck getting these to open or close using the command open/close using Alexa (not alexa helper).

Does anyone currently offer “Top Down Bottom Up” shades that integrate with ST?

None that I am aware of.