that all give me a hint that there’s some ZDO/ZCL support that I don’t know how to use. For basic ZCL attributes, it seems like I can set up a table of objects and just have my code update the values, and then underlying software will handle things like ZDO requests (read, write, subscriptions, etc.).
I can’t really find examples of how that’s done, though.
That is because the functions you are referring to are external to the radio and need to exist within your application. Your best source for that is www.zigbee.org
Oh, I see. Aren’t these functions in the XBee Programmable API? For example, the API has a file zcl_time.c which has a Digi International copyright notice on it … inside that are methods like zcl_time_set(). I’m just trying to figure out how to use them …
The Basic and Identify cluster examples might be a little simpler or more straightforward to use as a reference.
The ZDO/ZCL support is powerful enough that you can implement whatever custom attribute/command/cluster/endpoint functionality you need but can get a little involved.
Is there a specific problem you’re trying to solve?
and put an Xbee ZB Programmable inside the waterproof cylinder inside. I wrote a small, simple program to count pulses (and debounce them in software). To send data, I’ve taken a few liberties with ZDO and ZCL -mainly that I’m using a Report Attributes command but with no subscription requirement. There’s an implied “subscription” that changes should be sent as a Report Attribute to the coordinator.
To formulate the messages I built a little ZCL message builder library. It works like this:
void send() {
int rc;
int add_result;
init_assembly_buffer(&asy, buf, sizeof(buf));
add_zcl_header_with_mfg(&asy,
0, /* frame control */
0xBEEF, /* manufacturer id */
seq++,
ZCL_CMD_REPORT_ATTRIB);
/* ADD AS MANY OF THESE AS WE WANT ATTRS IN THIS MESSAGE */
add_result = add_zcl_attribute_float(&asy, 5, 123.4f);
if(add_result == SIMPLE_ZCL_OK) {
printf("Add float OK
");
}
/*
* Fill in the envelope
*/
wpan_envelope_create(&envelope, &xdev.wpan_dev, WPAN_IEEE_ADDR_COORDINATOR,
WPAN_NET_ADDR_UNDEFINED);
envelope.options = 0x00;
envelope.cluster_id = 0x9999;
envelope.profile_id = 0xAAAA;
envelope.dest_endpoint = 0x40;
envelope.source_endpoint = 0x40;
envelope.payload = buf;
envelope.length = zcl_builder_buflen(&asy);
rc = wpan_envelope_send(&envelope);
printf("send wpan_envelope_send() returned %d
", rc);
}
So to answer your question: I have the feeling I shouldn’t have to do any of this … because the XBAee Programmable libraries will just let me declare that I have these attributes, and then the normal read/write/subscribe ZDO commands will just work.
You need to build up a structure going all the way from your attribute definition (with a callback to return its read value), to a list of attributes for your custom cluster, the cluster itself containing your attributes, the endpoint containing your cluster, and finally the overall endpoint structure for your node.
The best example to work from in the given source code for your case is likely identify.c/h.
Does a little more than you need (custom commands in addition to custom attribute) but it has a single attribute with read callback. Check out ZCL_CLUST_ENTRY_IDENTIFY_SERVER and zcl_identify_attribute_tree for your primary hooks in.
I’d recommend trying to integrate the identify server into your code, make sure you can read its attribute then morph it into something that fits with your specific needs. Change attribute type, callbacks, etc.
When the callback gets called, does the normal response generation still work if it’s a standard ZDO request like “read attribute”? Or am I responsible for generating the response?
Where you have NULL is the attribute tree that defines your attribute. With that in place you wouldn’t need the custom handler unless, like the Identify cluster, you are adding additional custom commands. All of the attributes are automatically handled as specified in the attribute tree.
Take a look at how the attribute tree is defined for the Identify cluster and you should be able to piece together how to do something similar for your use-case.
What happens if someone tries to use a command not supported by the SDK ZCL/ZDO layer? For example:
#define ZCL_CMD_CONFIGURE_REPORT 0x06
It looks like in zigbee_zcl.c in this function:
zigbee_zcl_debug
int zcl_general_command( const wpan_envelope_t FAR *envelope, void FAR *context)
that it falls through to:
return zcl_invalid_command( envelope);
Is it possible to have your callback handle this? Or, if I want to use subscriptions (reporting) would it be better to just have my callback handle everything?
I don’t believe the library comes with support for reporting. However, you can definitely add your own support especially if only for a limited subset of the functionality to make life simpler.
Refer to the zcl_identify_command() function that is provided for the Identify cluster I’ve been referencing so far. That shows a custom handler to peel off and handle certain commands. Any commands that aren’t processed it then passes into the default zcl_general_command() function.
So define something similar to catch and process reporting commands and add it to your cluster definition.
It is true that Digi does not provide examples nor good documentation when it comes to ZigBee ZDO/ZCL support. I suspect this could be a licensing related issue as ZigBee specification is provided publicly only for non-commercial purposes. In any case wanted to add an example to get ZDO support working in the Programmable XBee using the built in ZDO code. Hope this is of help to someone.
By default if your AO parameter is either 0 or 1, the XBee radio firmware will respond to the ZDO requests. The easiest to try this out is by sending “Active Endpoints Request” (Cluster ID 0x0005) to the module. The module will respond with E8 (Digi Endpoint) and E6 (Digi Command) being available. When AO is set to 3 or if you have one of the following defined in your project:
or directly ENABLE_XBEE_HANDLE_RX_ZCL_FRAMES which sets AO=3 at boot, you will notice that you will not receive any reply for the ZDO Active Endpoints Request - because by default ZDO endpoint is not added to active list. To do so, you need to:
Create a global for ZDO transaction tracking.
wpan_ep_state_t zdo_ep_state;
Add the ZDO endpoint to the list in custom.h (based on xbee_custom_endpoint example):
To my knowledge, that is still the only way - officially. For Programmable XBee Development, the SDK is delivered in form of CodeWarrior IDE for MCUs (v10.2), which is Windows Only. On top of that you need the actual SDK containing the necessary source code, documentation and samples - everything wrapped in an installer (.exe)
I’m not a Windows user myself so I went ahead and:
Having said that there are options to work with Programmable XBee’s without Windows, all the sample applications are generated via a simple wizard and majority of the project defines are generated through a smart editor available only on the CodeWarrior. It will be a bigger challenge to work with the platform on any other OS.