ZigBee Temperature reporting question for Cluster 0x402

I’m working on a new device driver for a ZigBee thermometer that has two temperature probes (one for inside and the other for outside). Each probe is on a unique end-point. Everything works as expected as far as querying the attributes of each end point and getting that probe’s temperature. All is good there.

However, when I configure the device to report its attributes to the hub it does so for each end point but what is delivered to the parse method is a string with the word “temperature” and the value, not the “catchall” string. I have no clue what end point this came from so I cant associate it with the correct probe. Is there a way I can find the source end point for this reported temperature?

1 Like

@Jim @Mager @slagle who is answering SmartThings/zigbee questions for developers now that Urman is no longer on staff?

These aren’t zigbee questions per se, but rather questions about the reporting layer for zigbee devices that ST has built into its device handler model.

@JohnR I know you probably know this, but does anything respond on join that advertises the clusters and endpoints on the zdo bind or join actions?

Also, in the parse method, are you getting a raw message that is being translated via the zigbee parser or is it actually responding with temperature?

Did you bind it to that endpoint or did the device just start sending these statuses to the parse?

Patrick, sorry I’m not sure how to respond to that question but maybe this will help shine some light on what is going on:

From a communication stand point (at the ZigBee level) everything is working perfectly. My device type’s foot print matchs with the device and fires the configuration method as it should. The configuration method binds the hub to 3 end points on two clusters and that all works great. Those end points start sending reports as expected. I don’t have any problems in talking to the device and getting data back its how I’m getting the temperature report back that is just making me scratch my head.

Patrick, I know you know this next bit but I want to state it so I can set a base line for what is going on:

With a ZigBee device there are two ways to get information out of a cluster’s attribute. The first way is to send a read attribute command to the cluster and endpoint’s address . That is what the poll method is often used for in the custom device type. And this works great no problems! I can read the temperature of both end points all day long!! They come in like this:

description: catchall: 0104 0402 39 01 0C40 00 0509 00 00 0000 01 01 000000290080

The second way to get information from a ZigBee device is to configure its reporting, and bind to the cluster / endpoint. That is what happens when the configure method fires. Once a ZigBee device has been configured to report one of its attributes and has been bound to the hub it will send reports from that point on. This also works for me I can bind to the two temperature end points and they both send reports to the hub. The problem is instead of the catcall string I was getting above what I get is this:

description: temperature: 35.00

That would work for me except I have two thermostats in this device and they both report on unique endpoints. In the above description I don’t get the endpoints. So I cant match up the value to the correct probe.

It looks like there is a method parsing the temperature report and handing me the result instead of passing the whole packet like in the catchall above. IF I could find a way to get the endpoint of that report I will be good to go!!



Got it. So the reporting binding is on the temp cluster, so ST is out-thinking itself and parsing back the description of the response to 35 and mapping that to temp?

The issue is you aren’t seeing the endpoint it came from so no way to know which temp it is.

Out of curiosity, when you get that "event’ parse, have you tried dumping the whole message out before it tries to parse it, or is the whole “raw” message just “description: temperature: 35.00”?

It seems like ST is just reporting the description part of the parsed zigbee message and one should be able to get the event.cluster and event.endpoint if you dig into it. But that might not be exposed?

Yep your dead on my friend!! Kind of blows my mind why they would do something like this I have to be missing something?? Oh and that is the “raw” message!!

1 Like

So that does confirm my suspicision that ST is “preparsing” messages before reaching the parse function.

Only raw or catchall or un “preparsed” messages make it completely through.

Grrrr… Hopefully there is someone at ST that might be able to shed some light on the preparsing of messages of zigbee devices.

Running into something similar with a Card Access device that has multiple temp endpoints. On poll I can get the messages for both, but on subscribe to the report, I don’t get anything usable.


If they did it hear for the temperature device I wonder what other device reports are going to be intercepted and changed. Also makes me wonder if they are going to add more down the road breaking what people have working today. Or maybe the rule is if the cluster is tied to one of their official device types it will always be intercepted. But I don’t think that is the case??

I don’t want to go all negative on this I know I have to be missing something!!. I went back to double check I’m dumping the raw input. Here is my parse method:

def parse(String description) {
log.debug “description: $description”

Map map = [:]
if (description?.startsWith(‘catchall:’)) {
map = parseCatchAllMessage(description)
else if (description?.startsWith(‘read attr -’)) {
map = parseReportAttributeMessage(description)
else if (description?.startsWith('temperature: ') || description?.startsWith('humidity: ')) {
map = parseCustomMessage(description)

log.debug "Parse returned $map"
return map ? createEvent(map) : null

It sure looks like the parse method just gets passed a string not an object. So if I log.debug the string that should be all the data I have to work with right?

1 Like

I wonder if the parent object of the description is accessible?

I’m mobile right now and can’t remember the groovy to access it but also try removing the string from the message in the function parse and see if a map is returned. Maybe forcing it to string removes the map in parse?

Gave it a try and get the exact same text when I dump the description with debug log.

Heading down to the boat to get her cleaned up for the weekend. Have a good weekend up there!!

Hi @JohnR, Do you mind sharing your code? How does your configuration looks like? Are you binding before asking for send-me-a-report?

"zdo bind 0x${device.deviceNetworkId} **1 ${endpointId}** 0x20 {${device.zigbeeId}} {}", "delay 400",
"zcl global send-me-a-report 1 0x20 0x20 600 3600 {01}", "delay 200",
"send 0x${device.deviceNetworkId} **1 ${endpointId}** ", "delay 1500",

private getEndpointId() 
	new BigInteger(device.endpointId, 16).toString()

Are you hardcoding the device endpointId in the configure() method?

1 Like

I’m using the default report configuration of the device which sends a new temperature report any time the temperature value changes. As I said above I’m getting the reports from the device its just they are being intercepted and the source end point is getting stripped out before it is handed to my parse method.

Here is my configure method:

def configure() {
log.debug "Binding SEP 0x38 DEP 0x01 Cluster 0x0101 Lock cluster to hub"
log.debug "Binding SEP 0x39 DEP 0x01 Cluster 0x0402 Temperature cluster to hub"
log.debug “Binding SEP 0x40 DEP 0x01 Cluster 0x0402 Temperature cluster to hub”

def cmd = []
cmd << "zdo bind 0x${device.deviceNetworkId} 0x38 0x01 0x0101 {${device.zigbeeId}} {}"			// Bind to end point 0x38 and the lock cluster
cmd << "delay 150"
cmd << "zdo bind 0x${device.deviceNetworkId} 0x39 0x01 0x0402 {${device.zigbeeId}} {}"    		// Bind to end point 0x39 and the temperature cluster
cmd << "delay 150"
cmd << "zdo bind 0x${device.deviceNetworkId} 0x40 0x01 0x0402 {${device.zigbeeId}} {}"    		// Bind to end point 0x40 and the temperature cluster
cmd << "delay 1500"    

log.info "Sending ZigBee Configuration Commands to Coop Control"
return cmd + refresh()

As you can see I’m not sending any send-me-a-report commands because I’m using the device’s default configuration. I don’t think the problem is in the configure method as I’m getting the reports just fine so these bind commands are being received and understood.


Hi @JohnR:
Can you please try this in your code?

def configure() {
    "zdo bind 0x${device.deviceNetworkId} ${sourceEndPoint} ${destinationEndpointId} cluster {${device.zigbeeId}} {}"

It seems you are binding only in cluster 1.


Yaima, I’m not following your suggestion. I’m binding to three end points. The first endpoint is 0x38 for the door cluster 0x0101, the next two endpoints are 0x39 and 0x40 both with the same cluster number 0x0402 Temperature. Those endpoints are being bound to your hubs 0x01 endpoint. Do I need to send them to different end points on your hub?? I have always used 0x01 as my destination endpoint when talking to your hub.

Did you mean to say “It seems you are binding only to destination end point 1”??

Can you please try this:

def cmd = []
cmd << "zdo bind 0x${device.deviceNetworkId}  0x01 0x38 0x0101 {${device.zigbeeId}} {}"			// Bind to end point 0x38 and the lock cluster
cmd << "delay 150"
cmd << "zdo bind 0x${device.deviceNetworkId} 0x01 0x39 0x0402 {${device.zigbeeId}} {}"    		// Bind to end point 0x39 and the temperature cluster
cmd << "delay 150"
cmd << "zdo bind 0x${device.deviceNetworkId}  0x01 0x40 0x0402 {${device.zigbeeId}} {}"    		// Bind to end point 0x40 and the temperature cluster
cmd << "delay 1500"    

log.info "Sending ZigBee Configuration Commands to Coop Control"
return cmd + refresh()

Bind from the hub to the device endpoint and cluster.

@JohnR, is your device in this list: http://www.zigbee.org/zigbee-products-2/#zigbeecertifiedproducts/?view_30_filters=[{"field"%3A"field_41"%2C"operator"%3A"is"%2C"value"%3A"551c72aa37b6dfa00fb984a5"}]&view_30_page=1
so I can take a look at the specs?

So your saying I should set my Source Endpoint to 0x1 and my destination endpoint to 0x38, 0x39, or 0x40? I think one of us has got this backwards. I’m binding my device’s Source Endpoint to your hub’s Destination Endpoint right? If I do as you suggest wont that be backwards? At least according to your documentation http://docs.smartthings.com/en/latest/device-type-developers-guide/building-zigbee-device-handlers.html#zdo-bind

Again I think my binding commands are fine I’m getting the reports from my device. I see the temperature reports come in as the temperature changes. I wouldn’t get those reports if the bind command wasn’t being understood and processed by my device.

I don’t mean to be hardheaded its just if I screw up the device’s binding table I will have to reinstall it and I have it outside in a test jig right now.

It will be a couple of weeks before I can give your suggestion a try. Thanks for the help!

1 Like

This is a new device its not on the certification list. Thanks again for your help!

That’s exactly what I am saying and this knowledge comes from Silicon Labs.
We have sniffers available that could use to trace the activity coming from your device, but it seems you are not willing to provide any additional information. I am here to help if you need anything else, it is always my pleasure.

Well then I bet I have it backwards. What makes me scratch my head is why it works and other device types I have written with the same order of source and destination work just fine. But anyway I will give it a try and see what happens. Thanks!