[HOW-TO] Using the Z-Wave Association Tool in SmartThings

What code do I need to add to non-inovelli DH to get them to work with the Z-Wave Association Tool?

You have to add the following methods (below). You also need the command “processAssociations()” somewhere appropriate for the specific device. If it is a sleeping device it needs to have this in its WakeUp Notification method. If it is an “always awake” device, it can be put in its “updated()” or “refresh()” method. That method returns the commands as “un-formatted” z-wave commands so they need to be formatted at one point. For example:

def cmds = processAssociations()
return commands(cmds)

private command(physicalgraph.zwave.Command cmd) {
    if (state.sec) {
        zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
    } else {
        cmd.format()
    }
}

private commands(commands, delay=1000) {
    delayBetween(commands.collect{ command(it) }, delay)
}

Those previous two methods may not be necessary. It just depends on how you are sending commands through the hub.

def setDefaultAssociations() {
    def smartThingsHubID = (zwaveHubNodeId.toString().format( '%02x', zwaveHubNodeId )).toUpperCase()
    state.defaultG1 = [smartThingsHubID]
    state.defaultG2 = []
    state.defaultG3 = []
}

def setAssociationGroup(group, nodes, action, endpoint = null){
    if (!state."desiredAssociation${group}") {
        state."desiredAssociation${group}" = nodes
    } else {
        switch (action) {
            case 0:
                state."desiredAssociation${group}" = state."desiredAssociation${group}" - nodes
            break
            case 1:
                state."desiredAssociation${group}" = state."desiredAssociation${group}" + nodes
            break
        }
    }
}

def processAssociations(){
   def cmds = []
   setDefaultAssociations()
   def associationGroups = 5
   if (state.associationGroups) {
       associationGroups = state.associationGroups
   } else {
       if (infoEnable) log.info "${device.label?device.label:device.name}: Getting supported association groups from device"
       cmds <<  zwave.associationV2.associationGroupingsGet()
   }
   for (int i = 1; i <= associationGroups; i++){
      if(state."actualAssociation${i}" != null){
         if(state."desiredAssociation${i}" != null || state."defaultG${i}") {
            def refreshGroup = false
            ((state."desiredAssociation${i}"? state."desiredAssociation${i}" : [] + state."defaultG${i}") - state."actualAssociation${i}").each {
                if (it != null){
                    if (infoEnable) log.info "${device.label?device.label:device.name}: Adding node $it to group $i"
                    cmds << zwave.associationV2.associationSet(groupingIdentifier:i, nodeId:Integer.parseInt(it,16))
                    refreshGroup = true
                }
            }
            ((state."actualAssociation${i}" - state."defaultG${i}") - state."desiredAssociation${i}").each {
                if (it != null){
                    if (infoEnable) log.info "${device.label?device.label:device.name}: Removing node $it from group $i"
                    cmds << zwave.associationV2.associationRemove(groupingIdentifier:i, nodeId:Integer.parseInt(it,16))
                    refreshGroup = true
                }
            }
            if (refreshGroup == true) cmds << zwave.associationV2.associationGet(groupingIdentifier:i)
            else if (infoEnable) log.info "${device.label?device.label:device.name}: There are no association actions to complete for group $i"
         }
      } else {
         if (infoEnable) log.info "${device.label?device.label:device.name}: Association info not known for group $i. Requesting info from device."
         cmds << zwave.associationV2.associationGet(groupingIdentifier:i)
      }
   }
   return cmds
}

def zwaveEvent(physicalgraph.zwave.commands.associationv2.AssociationReport cmd) {
    if (debugEnable) log.debug "${device.label?device.label:device.name}: ${cmd}"
    def temp = []
    if (cmd.nodeId != []) {
       cmd.nodeId.each {
          temp += it.toString().format( '%02x', it.toInteger() ).toUpperCase()
       }
    } 
    state."actualAssociation${cmd.groupingIdentifier}" = temp
    if (infoEnable) log.info "${device.label?device.label:device.name}: Associations for Group ${cmd.groupingIdentifier}: ${temp}"
    updateDataValue("associationGroup${cmd.groupingIdentifier}", "$temp")
}

def zwaveEvent(physicalgraph.zwave.commands.associationv2.AssociationGroupingsReport cmd) {
    if (debugEnable) log.debug "${device.label?device.label:device.name}: ${cmd}"
    sendEvent(name: "groups", value: cmd.supportedGroupings)
    if (infoEnable) log.info "${device.label?device.label:device.name}: Supported association groups: ${cmd.supportedGroupings}"
    state.associationGroups = cmd.supportedGroupings
}

I am curious how you got this working such that the LEDs stay in sync locally. I don’t see a parameter 12 anywhere when I look in the smart things IDE at this device or in the settings for the device. I have the 2 switches wired up as described in the manual, and have the association from the switch that doesn’t directly control the light to the destination switch (that is wire directly to the light). However, the dimming LEDs do not stay in sync.
Can you screenshot where you found this setting (param 12)?

I do this using Hubitat not smartthings. I don’t know if smarthings has that in their device handler. It could possible be named association behavior but looking at your screenshot it doesn’t look like it is there.

I found if that parameter wasn’t set properly that a loop between my switches was created that flooded my zwave network and my hub.

There is a problem when you associate two devices together as @GavinCampbell has mentioned. It creates a loop of Z-Wave commands that can cause big problems. It is because the device sends a switchmultilevel command to the other and because of the association it is designed to send the same command to the other device which then does the same and the process goes on forever. I can’t think of a way to prevent this from happening in that scenario (switch a <–> switch b). This problem doesn’t exist in a one way association though (switch a --> switch b). This is sometimes called a master / slave association and it works well in most situations.

The problem I am having with the one way association though is that it does still seem to take seconds for the slave switch to turn on the lights when the master switch is toggled. I understand that this is because a physical electrical current isn’t being completed since the master switch isn’t in the loop, but I would expect that command to get to the slave switch much quicker and be on the order of milliseconds.

Correct. However parameter 12 which is exposed in the HE driver allows the adjustment so only physical taps are transmitted. The 2nd switch would then get a virtual command and not send it back. This is how I got it working when using the switches. The only downside is any virtual commands are not mirrored.

Even if you try to do via an app on your controller you have to be careful of the same looping situation.

If there was an option in the driver to say ‘don’t send commands received via association channels’ we could get this working.

Maybe a future update.

Why it is working with parameter 12 is because if you disable the z-wave command association responses, it will ignore these. The negative with that is that the switches no longer stay in sync when you adjust them from the hub.

The problem I see is that when you change a switch locally it sends the same command as when you change it from the hub. That is why disabling the z-wave part of parameter 12 makes it works locally (it interprets the command as a z-wave command).

Since the commands are the same the switch has no way of telling them apart. For example, when you use Hubitat to change the level it sends:

SwitchMultiLevelSet(x%)

When you adjust the switch locally it sends the following command to the other switch:

SwitchMultiLevelSet(x%)

The command doesn’t specify where it came from or how it came about. So it is definitely something that would be great to fix in firmware, but I currently am not seeing a way to do it.

2 Likes

Maybe the solution for remote control in @GavinCampbell 's setup is to use a virtual device for remote control that receives commands and then sends them individually to each switch. You would then just have to not send them individual commands other than through the virtual device.

2 Likes

Hi! What are Groups 1, 3, and 5 used for with the Association Tool? I have not been successful in finding the answer during my searches. Thank you!

Group 5 isn’t used on this device. The rest of them are defined in our manual. Group 1 is usually only associated with your hub.

I’m having some troubles, and I’m not sure if I’m doing something wrong. I was having the same issue when trying to use Zwave tweaker instead of this app, but this app is definitely more user-friendly.

I have a red series switch, and 3 RGBW bulbs. The switch doesn’t control an actual load. I want to associate the switch with the 3 bulbs, but no matter what I try, it seems to only grab the first bulb that I check in the list. When I was using a comma-separated list of IDs in Z-wave tweaker, I had the same issue… just the first bulb. Am I missing something to make my switch control all 3 bulbs?

Hey @Jonathan, this is a known bug for the ON / OFF switch firmware. When the device is using S0 security it only sends the association commands to the first device in the association list.

This is fixed in a new firmware. I am about to post a link to it.

Edit: Firmware v1.16 (Beta) | LZW30-SN | Switch - Red Series (Gen 2) - #2 by EricM_Inovelli - Firmware Discussion - Inovelli Community

@EricM_Inovelli thanks, that worked perfectly. I half expected that my decade old Z-wave stick wouldn’t have worked for some reason – but no issues updating it, and now my switch is controlling all 3 bulbs!

1 Like

I am struggling getting my security levels to play nice…

I have 6 ilumin bulbs and several red series dimmers.

I am trying to get them to associate and struggling to get desired devices at the right security levels.

All of the bulbs are pairing in at * networkSecurityLevel: ZWAVE_S0_LEGACY which honestly is fine with me as I’ve heard that the additional security just generates wasteful overhead in the mesh.

1 switch paired in at the same * networkSecurityLevel: ZWAVE_S0_LEGACY which works perfectly with the association just as I would like for it to do.

Other switches pair in at * networkSecurityLevel: ZWAVE_S2_AUTHENTICATED.

I can “sabotage” the security pairing by intentionally failing to scan the QR code when it’s requested, but that results in * networkSecurityLevel: ZWAVE_S2_FAILED

anyone got any tips on how to pair these switches in at S0 ? that seems ideal for speed and interoperability with the lights.

As a backup, how can I get the bulbs to pair in at S2? they seem to pair fast and one is only 2 feet away from the hub so I know it’s not a range thing… but they only want to pair in at S0. (side note I did pair all the bulbs before installing the bulb device handler… would they now pair at S2 since I have the handler?)
edit: tried excluding and pairing one of the bulbs now that the handler is installed. Bulb that’s 2 foot away from the hub still paired in at S0… so I guess that’s not it.

thanks!

Hey so I actually ran across this myself and was getting super frustrated.

What I ended up doing to get it to work was bring the bulb extremely close to the hub to pair it. It ended up pairing w/S2.

I think I brought them within maybe 6ft of the hub.

Just remember to do a Z-Wave refresh once you move the bulb to its final location.

Let me know if that helps!

1 Like

Thanks for the response I’ll keep plugging away at it see if I can get these bad boys to play nice.

I think that security level may be the same as ZWAVE_S0_LEGACY so you might want to try to associate it. Also, you can use the classic app as an alternative to sabotaging the S2 pairing. They didn’t build S2 pairing into the classic app so the highest it can go is S0.

the classic app trick might be JUST what the doctor ordered!

1 Like

Hi @EricM_Inovelli I’m trying to get this to work with an LZW30-SN & a GE 46201 switch

I’m using this hubitat driver for the GE switch: https://raw.githubusercontent.com/Botched1/Hubitat/master/Drivers/GE%20Enbrighten%20Switch/GE%20Enbrighten%20Switch.groovy

Can you tell me exactly where i need to add the new code to make the associations work?