My Somfy-SmartThings Integration

I was using his and then I used routines with dimmer calls for my blinds to tilt, etc. I was the one who started this thread, scroll ALLLLLL the way to the top and it explains everything.

The functionality of dimmer should not have changed. Again, when installing the new driver, one time the state variables need to get updated. This is done by issuing a command to the device handler (in things in phone app)

I think if I re-read my post, I actually modified his device type forgetting about that minor detail. Now I am using yours and noticing issues, which is probably my own fault. I need to debug the code again. Honestly, I just use my 3 routines (Open Blinds, Close Blinds and Lift Blinds) 95% of the time. The one time I wanted to control a single shade is when I need to drill into the device itself…

Post your code, perhaps the changes should be merged…

Below is my updated code which needed quite a bit of changing up. This might help some folks who have my types of motors/shades as I do believe there are a lot of combinations and preferences out there. My blinds have 3 states:

  • Open (Where the slats are open)

  • Up (Where the blinds are lifted up)

  • Closed (Where the slats are closed (also MyStop setting).

Also, in my case, when the blinds are in the Up state, the setlevel is 100, when they are open, they are 0, and when they are closed, they are 50. I am not sure why they are like this, but this is how it was setup. I modified all of the status messages, icons, etc. as well. As a result, I modified all of the code that works for me and renamed tiles to make more sense. Another cool thing I did was use @bravenel’s Rule Machine to sync the status of my blinds. I typically use a routine to perform an action on “All Blinds” such as Close all Blinds. Well, previously, all of my blinds channels wouldn’t reflect what they actually were because I would only be making changes to All blinds. Now when I do that, Rule Machine waits a minute and sends the identical commands so they all have their status synced up. See screenshots below to see Blinds - Channel’s 1-4 all match “All Blinds” in the UP State.

This all works perfect now, and the only drawback is if someone changes the blinds with the Somfy remote, the status wouldn’t update in ST, but since I integrated this with Smartthings, there has been no need to ever use that remote between widgets and Alexa :slightly_smiling:

The code is below (sorry, never setup a Github repo before and didn’t have the time for it now).

/**
 * 
 * https://community.smartthings.com/t/my-somfy-smartthings-integration/13492
 * Modified ERS 2/12/2016
 * Changes:
 *        Shows if shades are in a my/stop state
 *        Multi-tile control
 *        Disable dual setLevel operations
 */
  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("up", label:'Up', action:"open", icon:"st.doors.garage.garage-open", backgroundColor:"#ffffff", nextState: "opening")
                attributeState("open", label:'Open', action:"close", icon:"st.doors.garage.garage-open", backgroundColor:"#ffcc33", nextState: "closing")
                attributeState("closed", label:'Closed', action:"presetPosition", icon:"st.doors.garage.garage-closed", backgroundColor:"#bbbbdd")
                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:'Up', action:"switch.off", icon:"st.doors.garage.garage-open", backgroundColor:"#ffffff"
            state "off", label:'Open', action:"switch.on", icon:"st.doors.garage.garage-closed", backgroundColor:"#ffcc33"
            state "default", label:'closed', action:"presetPosition", icon:"st.doors.garage.garage-open", backgroundColor:"#bbbbdd"
        }

        standardTile("on", "device.switch", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
            state("on", label:'Lift Up', action:"switch.on", icon:"st.doors.garage.garage-opening")
        }
        standardTile("off", "device.switch", width: 3, height: 2, inactiveLabel: false, decoration: "flat") {
            state("off", label:'Tilt Open or Bring Down ', action:"switch.off", icon:"st.doors.garage.garage-closing")
        }
        standardTile("stop", "device.level", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
            state("default", label:'Close or Stop', action:"switch level.setLevel", icon:"st.Transportation.transportation14")
        }
        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: "lifting up")
            newlevel = 100
            delayBetween([
                zwave.switchMultilevelV1.switchMultilevelSet(value: 0xFF).format(),
                sendEvent(name: "switch", value: "on"),
                sendEvent(name: "windowShade", value: "up")
            ], 5000)
        } else if (level <= 25) {
            sendEvent(name: "windowShade", value: "opening")
            newlevel = 0
            delayBetween([
                zwave.switchMultilevelV1.switchMultilevelSet(value: 0x00).format(),
                sendEvent(name: "switch", value: "off"),
                sendEvent(name: "windowShade", value: "open")
            ], 5000)
        } else {
            delayBetween([
                zwave.switchMultilevelV1.switchMultilevelStopLevelChange().format(),
                sendEvent(name: "switch", value: "default"),
                sendEvent(name: "windowShade", value: "closed")
            ], 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
//}
3 Likes

Here is an attempt at merging this into a single DH. I don’t have blinds so I have not tested the blinds portion.

In settings for the device (gear icon), you select shades or blinds. This has normalized the commands switch (on open, off closed) and for WindowShade.

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

2 Likes

Dang it. I have been calling everything “Blinds” when I really have “Shades” Guess I need to go rename everything.

Do we still need zRTSII Device Controller Device Type?

Just wanted to say thanks…got my Somfy blinds delivered and within an hour, had them automated with ST, because of this community. Even though I am still not sure whether I have blinds or shades… :wink:

Mark

3 Likes

Hi, I’m using your devise type for Somfy RTS controlled outdoor awnings. Works perfect except when awnings are closed device type is open and when awnings are extended the device type thinks closed. Is their an easy was to reverse this

Does the blinds type above help (3 or 4 back device handler) and setting it to blinds vs. shades?

Ok…little (lot) confused.
I have one shade up and running with the 5 channel wall remote.
Ready to setup Smartthings.
So i will install the code from Eric (E-Sch)…correct?
Then plug in the somfy and marry to Smartthings?
Then create node to work with my shade?
Am I missing anything before I start?
Thanks tons…still learning…

I did the following

installed the device handler:
https://github.com/imnotbob/SmartThings-1/blob/Develop/somfy_shades.groovy

Follow instructions in item #1 of this list starting at step 3:
Plug in the zWave RTSII Module into an outlet and follow the instructions to program your zWave Controller and blinds to your Smartthings controller (Manual83). For the channels (Virtual Node), in the ST app, you do Connect New Device, and then on the zWave RTS Controller, you add your virtual nodes. I had 5 virtual nodes, 4 blinds plus the "All Blinds: channel, They correspond to how my Telis remote is programmed. In my case

If you are using blinds vs. shades, edit the devices you created to set them to blinds (My Home -> Things select your created device and edit with the “gear”)

I am also a bit new to smarthings and custom controllers and am having some trouble with my ZRTSII device.

  • Followed steps 1 and 2 with no problem

  • On the first attempt, I plugged in my ZRTSII controller, and went to base node include mode, then went to the smartthings app to connect the device, smartthings found the controller and I was able to add it

  • However, on the actual ZRTSII outlet controller I never got the ‘base node include success’ indication, thus I was unable to add nodes.

Any help will be much appreciated, I will give it another try tonight.

I remember having issues with pairing the base node, and it took a couple times till it stuck.

Make sure ST is searching before you start base node include and give it a couple minutes. I also think I paired it close to the ST Hub, but I was having issues so I was trying all sorts of things. You may need to factory reset it if its partial paired.

Hopefully this helps. Once paired it has been working great.

Here is the manual since the link at the top is dead: http://www.automatedshadeinc.com/files/controls-somfy/somfy_1811265_zrtsi_instructions_new_07-2013.pdf

Thanks for your response Ben. Yes, I am following all the steps you detailed.

  • Putting ST into search mode

  • Then putting the ZRTSII into base mode include mode

  • Also, just as an FYI, i’m using the generic Z-Wave controller device code, i’m assuming this should still work

Then I have had success with ST adding the Z-Wave control module, however, the ZRTSII unit still says Base Node Include until it says Base node fail.

My ZRTSI is literally plugged in right next to the ST HUB, and ST is finding it. Unfortunately the ZRTSII is just failing to find.

But that’s a good thought, just in case I will try to reset the ZRTSII unit and giving it another few whirls.

If anyone else has other advice please chime in. Thanks Ben.

You will need to install the ZRTSII device handler in the IDE (step 1). I am not sure a generic controller will work.

Oh I thought Ash said that the default generic zwave controller was no different than Chris’s code?

Either way, I created a new controller with Chris’s code, and will try it when i get home. Thanks!

Ash
ASH RAJ
Mar '151
I just checked. He made two changes, but neither one makes a functional difference:
The generic device type has pointless On/Off tiles, so he got rid of those.
When you add a ZRTSI, the generic device type names it “Z-Wave Controller” and his names it “Somfy ZRTSI Controller.”

Other than that, the code is identical.

I used the generic device that the system automatically chose, I only installed the Shade/blinds dth

Really… someone should start a new thread with all the correct steps or update the first post.

I set up my shades 6 months ago then updated to @E_Sch device type. I do remember first connection was weird, I timed out on the ZRTSII a few times, it seemed really quick.

I still am unable to connect. Also, at the same time, i’m unable to reset my ZRTSII device. I’m getting a “zwave reset fail” error on the lcd of the plug in ZRTSII device…frustrated