ZigBee binding between two devices

Had anyone written a device driver that allows binding between two ZigBee devices? Not to the coordinator as usual. Like from a bulb to a switch. I’ve done this before with some custom software, but not with SmartThings.

It definitely seems possible but before I forge ahead I thought I’d check first.

I am able to bind my switch with a bulb, but it’s not very elegant. But at least I know the coordinator can do it.

I see that in a SmartApp there can be preference section like “capability.switch”. This doesn’t work in a device as indicated here:


Is there some way I can select the device to bind to from the switch device preferences? Or will I need to write a SmartApp to do this?

A device is bound to a device type by its “Type”. That type can be changed in the IDE, that is, you can choose the device type to bind a device to. Device types have “capabilities”. When you install a SmartApp, you can select which devices whose device type possess a specific capability are connected to that app.

Okay I think I understand that part. But can I select devices (based on capabilities or otherwise) in the preferences dialog of a “Device”? This doesn’t seem to work. If I use a “SmartApp” then it works and I can select different devices in the preferences dialog.

No. [20 chars…]

Okay, thanks for the feedback. I’m still learning the ins and outs, and it doesn’t help that this project is pretty technical.

Basically what I need is to have the ZigBee id and endpoint of the two desired devices, and then I can execute the “zdo bind” command on the coordinator (hub).

I can see two options going forward. The way I have it working now is to have a parameter in the switch device (server) which contains the id and endpoint (of the client device) like so: “001122334455667788:1” and then the switch device executes the “zdo bind”. Ideally it would execute the bind command in the “updated()” method, but it doesn’t work. Do coordinator operations work in “updated()”? It seems like not, but I don’t know what would keep this from happening. I have it inside the “configure()” method and this is working, but it won’t run every time I change a parameter in the settings.

The second option is to have a SmartApp for each binding. This seems kind of silly because after the binding is complete, it’s done forever; the switch saves it to non-volatile memory. I guess the SmartApp could be deleted after the binding but this seems like even more of a kludge than entering the ZigBee Id like the first solution.

With more devices like the Lutron Connected Bulb Remote coming this binding functionality will be a great thing to have.

You should be able to call the configure() method from your updated(), so it runs every time device settings are changed. Make sure you have capability configuration in the metadata, so the configure() call will work.

Would it make sense for this to be a SmartApp/Device combo? The device could simply be a way to call the zdo bind. The SmartApp would let you choose the two devices, then send the id and endpoints to the device where the binding commands would be sent.

Sounds like your trying to do an end device bind. Take a look at this tread we are talking about the same thing. Lutron Connected Bulb Remote

The devices should initiate the bind process with a button push or some type of local action. You don’t need a custom device type to bind together two ZigBee devices on the same network as long as they both support an end device initiated bind. The hub will do it for you as long as you start the bind request from each device. For example this ZigBee power plug http://smartenit.com/product/zbmplug15/ can be bound to this ZigBee switch http://smartenit.com/product/zbws3b/ just by pushing their program buttons. The hub will do this automatically its built into the ZigBee spec.

What are the two devices you are trying to bind together?

I tried calling configure() from updated() and it doesn’t work either. There’s something funny going on. I could make this a SmartApp/Device combo but it’s not something that I need to do often so I’m not sure it’s worth that much overhead at this point.

I think this “End Device Bind” the same thing that TI calls “EZ-Mode”. I’ll read that spec, thanks for the info! In the past I’ve been able to simply bind two devices together using the coordinator. This works in SmartThings also but I haven’t found an elegant way to do it with the provided user interface, so maybe you’re right and I should just make it work a different way.

Is “End Device Bind” required for all HA devices?

I am working with a few different devices, some of which I’ve made myself. I have a ZigBee switch (battery powered energy harvesting) that I’m binding to various things like Cree bulbs and the Centralite modules. I’ve also made my own ZigBee desk lamp. If everything out there supports “End Device Bind” then that sounds like the way to go.

It depends on the device but yes for the most part to achieve ZigBee certification your device needs to support end device bind. So most of the devices you want to bind with should have it. Its pretty easy to do, it’s just one packet your device sends to the coordinator that contains a list of server and client clusters your device supports for binding. The Coordinator will then listen for other devices requesting to bind and match them up by cluster number. If it finds two devices that match it will send a bind command back down to the correct device. This bind packet is probably what your previous hub was sending. I know this worked with SmartThings V1 Hub, I haven’t tried it with V2 yet. I would expect it to still work.

I wish there was a straight forward way to do this with SmartThings as well as support for ZigBee groups, multi-cast addressing from a device type, and scenes but I don’t think that will ever happen.

Sure would like to hear more about what your working on! What radio and microprocessor are you using?

Sounds pretty doable, I’ll give it a go!

I’m using the TI CC2530 and CC2650. I’ve made a custom board, and also used the WeBee boards along with the new SensorTag. Here’s a couple pics: https://goo.gl/photos/YAkeW6AjsSWMJxP96 https://goo.gl/photos/6KAo6YHMsBXQ6qo96 https://goo.gl/photos/JvR7jsZddiTQVjVf7 Maybe I’ll start another thread for those? I’d make them open source if there is enough interest.

1 Like

Impressive board!! Looks very clean and very professional!!

So it seems like the return value from the configure() method is an array of strings to send to the ZigBee coordinator. Most other methods like on(), off(), etc support the same thing. But it seems like not all methods support this. Like it doesn’t seem to work with updated() and parse().

Is there some object method I can call to explicitly execute a ZigBee command?

Have you checked the the devicetype developer doc for Zigbee? Depending on the type of command, there is a particular syntax and/or command word, but you can also build a zigbee message/command using “raw 0xcluster {payload}” followed by a “send” command. I have only seen this used to send the enroll response for the IAS cluster.

For example: st cmd is used for general commands, st rattr is a read attribute command, st wattr is a write attribute command.

I’ve initiated write attribute commands from within the updated() method before, and the enroll response using raw is typically initiated from the parse() method, so it’s possible to initiate commands from any method.

In general, within ST if return isn’t specifically called, then a method will return whatever the last value is. You can also use [] to form it into a map of several commands like is often done in configure() and sometimes in refresh().

1 Like

Thanks for the help.

I am pretty sure that I’m doing the commands correctly. I even went so far as to take my configure() and rename it to updated(), without changing anything else. I could see it had executed by the logs when I finish editing parameters (actually it runs twice), but it didn’t send the packet. It worked perfectly fine as configure(), I could see the packet go out and the response come back.

I’m not sure why it works for you and not for me. Is there some code somewhere that does what I want, something I could try on my end? Thanks!

What kind of command is it? I wonder if ST limits certain commands like binds to the configure() method only. Might help if you post your sample and what you’re trying to do. That’s definitely odd that the command fires in one method and not another.

Here’s an excerpt from the updated() in the GE Link where I write to the transition time attribute for on/off commands (I figured you didn’t need to see the huge if/case statement to determine what the transition value should be).

def updated() {
    sendEvent( name: "attDimRate", value: "${dimRate}" )
    sendEvent( name: "attDimOnOff", value: "${dimOnOff}" )
    state.dOnOff = "0000"
    "st wattr 0x${device.deviceNetworkId} 1 8 0x10 0x21 {${state.dOnOff}}"


I was simply trying this:

def updated() {
log.debug “updated()”
[ “st rattr 0x${device.deviceNetworkId} 0x01 0x0402 0”, “delay 200” ]

Okay I tested the GE Link device type with my GE Link bulb. It doesn’t write the attribute on updated(). This explains why I couldn’t change the transition time when I tried it the other day! When I press the refresh button I can see the attribute being written.

Maybe it’s something particular to my setup, but now I’m thinking something changed with the backend that broke this functionality…

I think you’re right that a backend change may have been made. I added this option to the GE Link originally, and I remember testing it a bunch; so I’m almost positive the write attribute used to work from the updated() method.

Add: Just tried myself and it didn’t work from the updated() method.

Hey thanks for testing it out to confirm. I guess we’ll just have to wait until SmartThings (@workmonk ?)can have a look at it.

Have a simple null check for state?.dOnOff before you execute the write