Design Article
ZigBee applications - Part 5: Addressing within the node
Drew Gislason
8/2/2010 9:37 PM EDT
The example in this section, Example 4-9 ZigBee Endpoints, shows how a single node can support multiple endpoints. This example only uses two nodes, a ZC light and a ZR switch, but three different endpoints exist within each node.
The ZC light has three separately controllable lights in one node, while the ZR switch has three separate toggle switches in the other (see Figure 4.21). In this case, I've numbered the endpoints 1 through 3 on the switch, and 11, 22, and 33 on the light, just to show exactly which endpoint numbers are used doesn't matter much to ZigBee.

The user interface on this example is pretty simple (see Table 4.7). Each switch, SW1SW3, toggles a light. Each long switch, LSW1 – LSW3, binds that switch to the light when pressed on both nodes (light and switch). Feel free to bind any light to any switch. If binding a switch to multiple lights, use multiple End-Device-Bind sequences.
Compile and download the following projects into their respective boards:
- Chapter04\Example4-9ZigBeeEndpoints\ZcNcbHaOnOffLight.mcp
- Chapter04\Example4-9ZigBeeEndpoints\ZrSrbHaOnOffSwitch.mcp
| Switch | Use |
| SW1 | Toggles remote light bound on this endpoint |
| LSW1 | Binds EP1 |
| SW2 | Toggles remote light bound on this endpoint |
| LSW2 | Binds EP2 |
| SW3 | Toggles remote light bound on this endpoint |
| LSW3 | Binds EP3 |
| SW4 | Sends to the broadcast endpoint, which will toggle all three remote lights |
Next, press LSW1 on both the switch and the light to bind SW1 on the switch to LED1 on the light. Do the same with LSW2 and LSW3, on both boards. Now, press SW1 to toggle LED1, press SW2 to toggle LED2, and press SW3 to toggle LED3. Notice they are all independent of each other.
Feel free to reboot and bind them in any way you choose. These nodes don't keep track of binding after a reset, as a production-ready node might do. I often find it handy to have nodes forget what they know after a reset when making example code. The next chapter will describe how to save all of the information using Non-Volatile Memory.
Notice how the ZDO End-Device-Bind request, shown below and sent when LSW1 was pressed, includes which endpoint will be bound and which clusters the device is looking for:
Frame 42 (Length = 53 bytes)
IEEE 802.15.4
Frame Control: 0x8861
Sequence Number: 39
Destination PAN Identifier: 0x0f00
Destination Address: 0x0000
Source Address: 0x0001
Frame Check Sequence: Correct
ZigBee NWK
Frame Control: 0x0048
Destination Address: 0x0000
Source Address: 0x0001
Radius = 10
Sequence Number = 135
ZigBee APS
Frame Control: 0x00
Destination Endpoint: 0x00
Cluster Identifier: EndDeviceBindReq (0x0020)
Profile Identifier: ZDP (0x0000)
Source Endpoint: 0x00
Counter: 0x1d
ZigBee ZDO
Transaction Seq Number: 0x04
End Device Bind Request
Binding Target: 0x0001
Source IEEE Address: 00:50:c2:37:b0:04:00:02
Source Endpoint: 0x03
Profile ID: HA (0x0104)
Number Of Input Clusters: 4
Input Cluster List
Cluster 1: Basic (0x0000)
Cluster 2: Identify (0x0003)
Cluster 3: Groups (0x0004)
Cluster 4: On/off Switch Configuration (0x0007)
Number Of Output Clusters: 1
Output Cluster List
Cluster 1: On/off (0x0006)
In the Freescale solution, the list of endpoints is defined in EndPointConfig.c in a structure called, strangely enough, endPointList. Most nodes support just one endpoint. Some have a handful. This one has three on/off lights. A node could support a temperature sensor, thermostat, and light switch, or could support a variety of applications on different application profiles, including a private profile. Again, remember the three purposes of endpoints:
- Endpoints allow for different application profiles to exist within each node
- Endpoints allow for separate control points to exist within each node
- Endpoints allow for separate devices to exist within each node
const endPointList_t endPointList[3] = {
{&HaOnOffLight1_EndPointDesc, &gHaOnOffLightDeviceDef1},
{&HaOnOffLight2_EndPointDesc, &gHaOnOffLightDeviceDef2},
{&HaOnOffLight3_EndPointDesc, &gHaOnOffLightDeviceDef3}
};
The EndPointDesc field points to an endpoint descript which in turn points to a SimpleDescriptor. Simple Descriptors are a ZigBee construct that describes the endpoint in detail:
const zbSimpleDescriptor_t HaOnOffLight3_SimpleDescriptor = {
12, /* Endpoint number */
0x4, 0x1, /* Application profile ID */
0x0, 0x1, /* Application device ID */
0, /* Application version ID */
5, /* Number of input clusters */
(uint8_t *)HaOnOffLightInputClusterList,
0, /* Number of output clusters */
(uint8_t*)HaOnOffLightOutputClusterList,
};
Freescale also requires a device definition as part of their ZigBee Cluster Library support. If ZCL is not used, a device definition is not required. The device definition, among other things, points to common cluster routines and an instantiation of data for that endpoint. Different instantiations of data allow the three on/off lights to be controlled independently of each other.
One thing that's very important in Freescale's BeeStack: Be sure to register the endpoints. If an endpoint is not registered, then no data can be sent or received on that endpoint. The standard BeeAppInit() automatically registers all of the endpoints defined in the endpoint list:
void BeeAppInit(void)
{
index_t i;
/* register the application endpoint(s) */
for(i = 0; i < gNum_EndPoints_c; + +i) {
(void)AF_RegisterEndPoint(endPointList[i].pEndpointDesc);
}
...
}
The on/off light (ZcNcbHaOnOffLight) determines which LED to toggle based on the incoming endpoint. The incoming frame comes into BeeAppDataIndication(). Then the code is parsed by the ZCL function, ZCL_InterpretFrame(), which in turn calls on BeeAppUpdateDevice().
The application doesn't have to worry about data coming in on an unregistered endpoint: If the endpoint is not registered, the packet is thrown away. BeeAppUpdateDevice() is where the real work happens for turning the light on and off. It doesn't matter to the code in this example whether the endpoint starts at 1, 10, or 193, but it does assume the endpoints are contiguous:
void BeeAppUpdateDevice
{
(
zbEndPoint_t endPoint, /* IN: endpoint update happend on */
zclUIEvent_t event /* IN: state to update */
)
{
static const uint8_t aiLeds[] = { LED1, LED2, LED3 } ;
static const char acLeds[] = { ‘ 1 ’ , ‘ 2 ’ , ‘ 3 ’ } ;
static char szLightStr[] = " Light1 Off ” ;
uint8_t iLedIndex;
/* get an index into the endpoints */
iLedIndex = endPoint-appEndPoint;
if(iLedIndex > = gNum_EndPoints_c)
iLedIndex = 0;
szLightStr[5] = acLeds[iLedIndex];
switch (event) {
case gZclUI_Off_c:
ASL_SetLed(aiLeds[iLedIndex],gLedOff_c);
FLib_MemCpy(&szLightStr[7], " Off ” , 3);
ASL_LCDWriteString(szLightStr);
ExternalDeviceOff();
break;
case gZclUI_On_c:
ASL_SetLed(aiLeds[iLedIndex],gLedOn_c);
FLib_MemCpy( & szLightStr[7], " On ” , 3);
ASL_LCDWriteString(szLightStr);
ExternalDeviceOn();
break;
default:
ASL_UpdateDevice(endPoint,event);
}
}
This example showed how to use endpoints for multiple control points within a single node, both on the sending (switch) and receiving (light) side.
So why pick a particular endpoint number for any given application purpose, whether defining a control point, a new device, or a new profile within the node? If using a ZigBee public profile, such as Home Automation or Commercial Building Automation, the choice is completely arbitrary. I suggest starting at endpoint 1 and going up from there. If you are supporting multiple control points, keep them contiguous (e.g., 1, 2, 3) to make the C coding easier based on the destination endpoint number.
If using a private application profile, it is easiest to use a fixed endpoint for all devices in the network. The default endpoint in Freescale demo applications is 8. If using only one endpoint, just leave it there for private profiles. The network can then avoid the initial start-up discovery of endpoints and event save code-size by not including those functions. I'll talk more about endpoint discovery functions in Chapter 5, "ZigBee, ZDO, and ZDP."
|
Think of endpoints as virtual wires connecting applications.
Endpoints allow for separate profiles, devices, and control points to exist within a single node. |
Next: Clusters


t.alex
8/13/2010 8:25 PM EDT
Gislason, The article is pretty informative. I would like to clarify further the use of endpoints here. It seems we can choose to use any endpoint we want ? Or we should follow some standard defining which endpoint for which purpose?
Sign in to Reply
Tim.Gillman
8/30/2010 1:38 AM EDT
To find out more about ZigBee and Wireless Sensor Networking, go to Drew's website: www.sanjuansw.com
Sign in to Reply