datasheets.com EBN.com EDN.com EETimes.com Embedded.com PlanetAnalog.com TechOnline.com  
Events
UBM Tech
UBM Tech

Design Article

ZigBee applications - Part 5: Addressing within the node

Drew Gislason

8/2/2010 9:37 PM EDT

Example: ZigBee Endpoints

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.

Figure 4.21: ZigBee Endpoints Example

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

Table 4.7: ZigBee Endpoints Example UI
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



Please sign in to post comment

Navigate to related information

Datasheets.com Parts Search

185 million searchable parts
(please enter a part number or hit search to begin)