ZStack-Lighting-1.0.1 Host Interface C Examples

From Texas Instruments Wiki
Jump to: navigation, search

The ZStack-Lighting-1.0.1 Remote project includes a host interface that allows host processors to connect to a CC253x via UART and control the ZLL (ZigBee Light Link) network using an abstract ZLL API. This host interface is explained in section 6 of "Z-Stack Lighting API.pdf" which can be found in the "Z-Stack Lighting 1.0.1\Documents\API" folder. The Z-Stack-Lighting-1.0.1 installer can be downloaded from http://www.ti.com/tool/z-stack.

This wiki describes the ZLL Host Interface in more detail and provides C examples for compiling on a Linux Host Processor, but can be easily ported to other OS's. This code is shared a reference code to serve as a starting point when developing a host application based on the ZStack-Lighting-1.0.1 ZLL Remote Device.

ZStack-Lighting-1.0.1 Host Interface Limitation

There are 2 reasons someone would want to create a ZLL Host:

  • A portable high end ZLL Remote.
  • A fixed ZLL Controller.

The the ZStack-lighting-1.0.1 Host interface was implemented for a ZLL Remote, with high end remotes in mind, so implementing a ZLL Host controller using the ZStack-Lighting-1.0.1 Remote Sample Application has some limitations that need to be highlighted.

  • The ZLL Remote Sample Application is only implemented as an End Device, as such it can not create a network or act as a Router.
  • The ZLL Remote Sample Application must TouchLink with Lights in order to ascertain there network address and endpoint, which is needed for controlling them. This requires a proximity based touchlink with all the lights on the network.

For customers not developing a high end ZLL Remote, but instead developing a Fixed ZLL Controller Device these limitations are not acceptable and can be over come in the following ways:

  • Using a HA Coordinator Lighting Gateway (ZLL device are able to join HA networks using classical commissioning). This has been done in this wiki page http://processors.wiki.ti.com/index.php/ZigBee_Lighting_Gateway. This wiki supplies:
    • CC2530 HA Coordinator FW that implements device discovery and the ZStack-lighting-1.0.1 Host Interface
    • Host Linux ZigBee Gateway Server SW
    • Cloud Server Connection for control of Lights
    • Android Application for control of Lights and binding to HA lighting control devices (HA Switches and Occupancy Sensors).

OR

  • Create a ZLL Control Bridge application in ZStack-Lighting-1.0.1. This will be addressed in future releases of ZStack-Lighting.

ZStack-Lighting-1.0.1 Host Interface C Examples

A C example for Linux has been created that implements the ZStack-Lighting-1.0.1 Host Interface. The full source for the ZStack-Lighting-1.0.1 Host Interface C Examples is on a git and can be downloaded as a tar.gz from here.

2 modules are contained in the example:

  • zllSocCmd.c/h - This module contains the main functionality for ZStack-Lighting-1.0.1 Host Interface and exposes abstract API for sending commands and controlling ZLL devices.
  • zll_controller.c - This is an example application that uses the zllSocCmd module. It exposes the zllSocCmd functions through a command line.

HW Setup

alt text

To run these examples you will need:

  • ZStack-Lighting Remote:
    • 1 x SmartRF05+CC2530EM for programming as a ZStack-Lighting Remote and Light, available as part of the CC2530DK from here.
  • ZStack-Lighting Light(s):
    • SmartRF05+CC2530EM(s) for programming as a ZStack-Lighting Light(s) (2 available in above kit).

AND/OR

    • ZLight(s) for programming as a ZStack-Lighting Light(s), HW available soon.
  • Linux Machine or VM for building and running the Host Interface C Examples.
  • A serial to USB converter cable if the Linux Machine does not have a Serial Interface.

A SmartRF05-EB+CC2530EM must be programmed with the ZStack-Lighting-1.0.1 Remote FW and the SmartRF05-EB+CC2530EM(s)/Zlight(s) must be programmed with the ZStack-Lighting-1.0.1 Light FW. For instructions follow section 3 of the Z-Stack Lighting Sample Application Users Guide.pdf, which can be found in the "Z-Stack Lighting 1.0.1\Documents" folder.

The SmartRF05-EB+CC2530EM programmed as the ZStack-Lighting remote must then be connected to the Linux Machine via a Serial to USB cable (unless the Linux Machine has a UART interface and then it may be connected directly with a Serial cable).

Using ZStack-Lighting-1.0.1 Host Interface C Examples

The ZLL controller application provided allows you to control ZLL devices on the network from the commands line.

You must first build the example Linux application, if the native compiler of the Linux Machine is used the it is as simple as running Makefile, supplied in the example:

make
gcc -Wall -DVERSION_NUMBER="0.1"  -D_GNU_SOURCE -c -o zll_controller.o zll_controller.c
gcc -Wall -DVERSION_NUMBER="0.1"  -D_GNU_SOURCE -c -o zllSocCmd.o zllSocCmd.c
gcc -Wall -DVERSION_NUMBER="0.1" zll_controller.o zllSocCmd.o -o zllController.bin

If the native compiler is not used then you should change the gcc line in the make file to call the cross compiler:

GCC = gcc

Once the application is built you should launch it on the command line and specify the device that the ZStack-Lighting Remote appears as in you system. If using a serial to USB converter cable this is typically /dev/ttyUSB0:

./zllController.bin /dev/ttyUSB0
./zllController.bin -- Mar 20 2013 11:00:41

Before controlling the Lights you must first pair the ZLL Lights to the controller, this can be done by typing touchlink:

touchlink
touchlink command executed
 
processRpcSysApp: Command Received Successfully
 
 
tlIndicationCb:
    Network Addr : 0x0002
    End Point    : 0x0b
    Profile ID   : 0xc05e
    Device ID    : 0x0200
    Version      : 0x02
    Status       : 0x57
 
lcd_debug message from zll controller: EndDevice: 1 TL Light: 2

Once touchlinked the device can be controlled. Multiple device can be toudhlinked and device selection can be made through the -n<network address paramter>. The available commands are:

  • touchlink
  • sendresettofn
  • resettofn
  • setstate
  • setlevel
  • sethue
  • setsat
  • getstate
  • getlevel
  • gethue
  • getsat

The parameters are:

  • -n<network address>
  • -e<end point>
  • -m<address mode 1=groupcast, 2=unicast>
  • -v<value>
  • -t<transition time in 10ms>

A successful touchlink will set the network address and endpoint of the newly paired device. The newly paried Light can be turned on with the following command

  • setstate -v1

The below example will send a MoveToHue command to network address 0x0003 end point 0xb, which will cause the device to move to a red hue over 3s (be sure that the saturation is set high first to see the change):

  • sethue -n0x0003 -e0xb -m0x2 -v0 -t30

parameters are remembered, so the blow command directly after the above will change to a blue hue:

  • sethue -v0xAA

The value of hue is a 0x0-0xFF representation of the 360Deg color wheel where:

  • 0Deg or 0x0 is red
  • 120Deg or 0x55 is a green hue
  • 240Deg or 0xAA is a blue hue

The value of saturation is a 0x0-0xFE value where:

  • 0x0 is white
  • 0xFE is the fully saturated color specified by the hue value

Porting zllSocCmd Module To Your Application

Firstly the host needs to open the serial port to the CC253x, this is implemented in the function zllSocOpen.

zllSoc_fd = zllSocOpen( argv[1] );

A file descriptor is return so that the application can poll the CC253x device. This can be used to poll for input on the serial port, when data is available from the CC253x a processing function must be called to read and parse the message.

zllSocProcessRpc();

Messages from the CC253x are then transalted to call back functions. The host application can then register the following callback functions:

  • zllSocTlIndicationCb - TouchLink Indication callback
  • zllSocZclGetStateCb - ZCL response callback for get State
  • zllSocZclGetLevelCb - ZCL response callback for get Level
  • zllSocZclGetHueCb - ZCL response callback for get Hue
  • zllSocZclGetSatCb - ZCL response callback for get Sat

This is done by populating the callbacks in a callback table that the application is interested in receiving, setting ones that are not need to NULL, and passing it to the following callback registration function:

static zllSocCallbacks_t zllSocCbs =
{
  tlIndicationCb,        // pfnTlIndicationCb - TouchLink Indication callback
  zclGetStateCb,         // pfnZclGetHueCb - ZCL response callback for get Hue
  zclGetLevelCb,         //pfnZclGetSatCb - ZCL response callback for get Sat
  zclGetHueCb,           //pfnZclGetLevelCb_t - ZCL response callback for get Level
  zclGetSatCb           //pfnZclGetStateCb - ZCL response callback for get State
};
 
...
 
zllSocRegisterCallbacks( zllSocCbs );

Once the serial port is open the host can send commands using the following functions:

//ZLL API's
void zllSocTouchLink(void);
void zllSocResetToFn(void);
void zllSocSendResetToFn(void);
//ZCL Set API's
void zllSocSetState(uint8_t state, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode);
void zllSocSetLevel(uint8_t level, uint16_t time, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode);
void zllSocSetHue(uint8_t hue, uint16_t time, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode);
void zllSocSetSat(uint8_t sat, uint16_t time, uint16_t dstAddr, uint8_t  endpoint, uint8_t addrMode);
void zllSocSetHueSat(uint8_t hue, uint8_t sat, uint16_t time, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode);
//ZCL Get API's
void zllSocGetState(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode);
void zllSocGetLevel(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode);
void zllSocGetHue(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode);
void zllSocGetSat(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode);

ZStack-Lighting-1.0.1 Host Interface

The ZStack-Lighting-1.0.1 Host Interface is exposed using the MT (Management and Test) interface, this interface allow packets from the UART to be routed to the application running on ZStack. The UART packets containing the MT messages are formatted in accordance with the RPC (Remote Procedure Call) protocol explained in section 2.1 of "Z-Stack Monitor and Test API.pdf", inside this RPC packet there is an MT header which specifies where the message should be routed within ZStack, in this case the MT header needs to be formatted in such a way the the message is routed to the ZLL application running in CC253x ZStack FW.

The packet structure is as follows:

RPC Message Format
RPC Header MT Header MT_APP Header ZLL_MT_APP / ZCL_MT_APP command RPC Frame Check Sequence

Remote Procedure Call

The RPC packet contains a SOF (Start Of Frame) byte to help synchronize the packets sent of the UART, followed by the RPC payload (an MT message in this case) and finally ending in an FCS (Frame Check Sequence).

RPC Packet Format
SOF Payload FCS
1 Byte 3 - 256 Bytes 1 Byte
  • SOF: Must be set to 0xFE
  • Payload: in this case it is the MT Message, see section xxx\n
  • FCS: See section xxx

Frame Check Sequence

The FCS can be calculated by the below C code:

/*********************************************************************
 * @fn      calcFcs
 *
 * @brief   populates the Frame Check Sequence of the RPC payload.
 *
 * @param   msg - pointer to the RPC message
 *
 * @return  none
 */
void calcFcs(unsigned char *msg, int size)
{
	unsigned char result = 0;
	int idx = 1; //skip SOF
	int len = (size - 1);  // skip FCS
 
	while ((len--) != 0) {
		result ^= msg[idx++];
	}
 
	msg[(size-1)] = result;
}

Management and Test Message

The MT message forms the payload of the RPC packet. The MT message format is shown in the below table:

MT Message Format
Length CMD0 CMD1 Data
1 Byte 1 Byte 1 Byte 0 - 251 Bytes
  • Length: The length of the MT Data (0 - 251)
  • CMD0: bits 7-5 are the Command Type and bits 4-0 are the subsystem ID
    • For MT_APP Commands the Command Type will be SREQ for messages sent to the CC253x and AREQ for messages sent from the CC253x
    • For MT_APP messages the subsystem ID should be set to 0x09
Command Type
Type Value
POLL 0x00
SREQ 0x20
AREQ 0x40
SRSP 0x60
  • CMD1: This is the MT_APP Command ID and should be set to 0.

MT APP Messages

There are 2 types of MT APP messages used in the ZStack-Lighting-1.0.1 Host Interface:

  • ZLL_MT_APP Message
  • ZCL_MT_APP Message

ZLL MT APP Message

The ZLL_MT_APP messages expose an interface to send commands that are specific to the ZLL profile. These messages can be thought of as control plane messages, they control the behavior of devices on the network (e.g. join or leave the network).

The structure of the ZLL_MT_APP message is shown below:

MT Message Format
Application End Point Reserved ZLL_MT_APP Cluster ID Date Len Reserved ZLL_MT_APP Command ID Reserved ZLL_MT_APP Command Payload
1 Byte 3 Bytes 2 Bytes 1 Byte 3 Bytes 1 Byte 2 Bytes x Bytes (defined by command)
  • Application End Point: This is the application endpoint of the ZLL application, it should be set to 0x0B
  • Reserved: All reserved bytes should be set to 0x00
  • ZLL_MT_APP Cluster ID: should be set to 0xFFFF
  • Date Len: This should be 6 + the number of parameters in the ZLL_MT_APP Command
  • ZLL_MT_APP Command ID: See below for supported commands

The ZLL MT APP Message currently supported by the ZLL controller application are:

ZLL MT APP Commands Sent to CC253x
ZLL_MT_APP Command Value Parameter (1 Byte)
ZLL_MT_APP_RPC_CMD_TOUCHLINK 0x01 N/A
ZLL_MT_APP_RPC_CMD_RESET_TO_FN 0x02 N/A
ZLL_MT_APP_RPC_CMD_CH_CHANNEL 0x03 Target Channel
ZLL_MT_APP_RPC_CMD_JOIN_HA 0x04 N/A
ZLL_MT_APP_RPC_CMD_SEND_RESET_TO_FN 0x06 N/A
ZLL MT APP Commands Sent from CC253x
Command Value Parameter
MT_APP_ZLL_TL_IND 0x81 EpInfo structure, eee below.
ZLL_MT_APP_RPC_CMD_TOUCHLINK

This command will cause the CC253x ZLL controller to start a Touch Link transaction. TouchLink is proximity based, so for a succulence TouchLink the traget light must be close the the controller. Where a typical distance is less than 2 meter, but this is dependent on the Antenna quality and environment.

This is discussed more in the "Limitations" section below.

ZLL_MT_APP_RPC_CMD_RESET_TO_FN

This command will cause the CC253x ZLL controller to reset to factory new. The controller will send out a network leave message to inform other devices that it is leaving the network. It will then reset after 5s.

ZLL_MT_APP_RPC_CMD_CH_CHANNEL

This command will cause the CC253x ZLL controller to initiate a channel change procedure the move the network to a new channel defined by the "Target Channel" parameter.

ZLL_MT_APP_RPC_CMD_JOIN_HA

This command will cause the CC253x ZLL controller to initiate a "Classical Join" procedure. The CC253x ZLL controller will scan for a ZigBee network and attempt to association in the classical ZigBee way.

ZLL_MT_APP_RPC_CMD_SEND_RESET_TO_FN

This command will cause the CC253x ZLL controller to send a "Reset To Factory New" Command. The current implementation requires that this is sent in the context of a TouchLink transaction, so first the user must initiate a TouchLink, then when the Target Light identifies the "Reset To Factory New" Command must be sent. Once the "Reset To Factory New" Command is received by a ZLL Light will still in a TouchLink transaction the Light will reset to factory new. In the TI implementation of a ZLL Light this means the Light will send a network leave command and then reset after 5s. Other implementation may vary slightly in the timing, but the end result will be the same.

ZLL_MT_APP_CMD Example

An example of formatting and sending an ZLL_MT_APP_CMD is shown below. In this example it is a ZLL_MT_APP_RPC_CMD_TOUCHLINK command:

/*********************************************************************
 * MACROS
 */
 
#define APPCMDHEADER(len) \
0xFE,                                                                             \
len,   /*RPC payload Len                                      */     \
0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP        */     \
0x00, /*MT_APP_MSG                                                   */     \
0x0B, /*Application Endpoint                                  */     \
0x02, /*short Addr 0x0002                                     */     \
0x00, /*short Addr 0x0002                                     */     \
0x0B, /*Dst EP                                                             */     \
0xFF, /*Cluster ID 0xFFFF invalid, used for key */     \
0xFF, /*Cluster ID 0xFFFF invalid, used for key */     \

#define BUILD_UINT16(loByte, hiByte) \
          ((uint16_t)(((loByte) & 0x00FF) + (((hiByte) & 0x00FF) << 8)))
 
/*********************************************************************
 * CONSTANTS
 */
#define ZLL_MT_APP_RPC_CMD_TOUCHLINK          0x01
 
...
 
/*********************************************************************
 * @fn      zllSocTouchLink
 *
 * @brief   Send the touchLink command to the CC253x.
 *
 * @param   none
 *
 * @return  none
 */
void zllSocTouchLink(void)
{
	uint8_t tlCmd[] = {
		APPCMDHEADER(13)
		0x06, //Data Len
		0x02, //Address Mode
		0x00, //2dummy bytes
		0x00,
		ZLL_MT_APP_RPC_CMD_TOUCHLINK,
		0x00,     //
		0x00,     //
		0x00       //FCS - fill in later
    };
 
    calcFcs(tlCmd, sizeof(tlCmd));
    write(serialPortFd,tlCmd, sizeof(tlCmd));
    tcflush(serialPortFd, TCOFLUSH);
}
MT_APP_ZLL_TL_IND

This command will be sent from the CC253x ZLL controller on a successful TouchLink. The message will contain the End Point Information of the Target device.

MT Message Format
Network Address End Point Profile ID Device ID Version
2 Bytes 1 Byte 2 Bytes 1 Byte 1 Byte
  • Network Address: 16b Network Address of the Target Device
  • End Point: End Point of the Target Device
  • Profile ID: Profile ID of the Target Device
  • Device ID: Device ID of the Target Device
  • Version: Version of the Target Device

The ZLL controller application must store the EndPoint info for sending ZCL_MT_APP messages to control lights on the network.

ZCL MT APP Message

The ZCL_MT_APP messages expose an interface to send commands that part of the ZCL. These messages can be thought of as data plane messages, they control the Lights in the network (e.g on/off, level etc). This interface can be used to support any ZCL command, developers should consult the ZCL Specification to decide which commands should be support by the product.

The structure of the ZCL_MT_APP message is shown below:

MT Message Format
Application End Point Network Address Destination End Point ZCL Cluster ID Date Len Address Mode ZCL Frame Control Field ZCL Transaction Sequence Number ZCL Command ID ZCL Command Payload
1 Byte 2 Bytes 1 Byte 2 Bytes 1 Byte 1 Byte 1 Byte 1 Byte 1 Byte x Bytes (defined by command)
  • Application End Point: This is the application endpoint of the ZLL application, it should be set to 0x0B
  • Reserved: All reserved bytes should be set to 0x00.
  • Network Address: Network Address (or groupId depending on address mmode) of the device to send the ZCL message to, network addresses of devices TouchLink are sent in the MT_APP_ZLL_TL_IND message.
  • Destination End Point: End Point of the device to send the ZCL message to, End Points of devices TouchLink are sent in the MT_APP_ZLL_TL_IND message.
  • ZCL Cluster ID: Cluster ID of the ZCL Command to be sent. See the ZCL Specification.
  • Date Len: This should be 6 + the number of parameters in the ZCL Command.
  • Address Mode: The address mode of the ZCL message:
Address Mode
AddrNotPresent 0
AddrGroup 1
Addr16Bit 2
Addr64Bit 3
AddrBroadcast 15

For most application only unicast message with an address mode of Addr16Bit or groupcast messages with an address mode of AddrGroup will be required.

  • ZCL Frame Control Field: Defines the characteristics of the ZCL frame:
Frame Control Byte
bit 7..5 bit 4 bit 3 bit 2 bit 1..0
Reserved Disable Default Response Direction (Client/Server) Manufacturer Specific ZCL Command Type
  • ZCL Frame Control Field bits:
    • Reserved: Should be 0x0
    • Disable Default Response: defines if the receiver should send a default response on receipt of the ZCL message.
    • Direction (Client/Server): defines if the messaging is destined for the Client or Server of the cluster.
    • Manufacturer Specific: defines if the is a ZCL messages defined by the ZCL Spec or if it is a manufacturer specific extension.
    • ZCL Command Type: Defines is the command specific to a cluster. For example an On/Off messages is specific to the On/Off cluster, but a ZCL read of the on/off attribute is not.
  • ZCL Transaction Sequence Number: The transaction ID should be incremented for each ZCL message.
  • ZCL Command ID: Command ID of the ZCL Command to be sent. See the ZCL Specification.
  • ZCL Command Payload: Payload of the ZCL Command to be sent. See the ZCL Specification.
ZCL_MT_APP_CMD Example

The below shows and example of an formatting and sending a ZCL_MT_APP_CMD message. In this case it is a MoveToLevel command:

#define COMMAND_LEVEL_MOVE_TO_LEVEL          0x00
#define ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL     0x0008
 
...
 
/*********************************************************************
 * @fn      zllSocSetLevel
 *
 * @brief   Send the level command to a ZLL light.
 *
 * @param   level - 0-128 = 0-100%
 * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
 * @param   endpoint - endpoint of the Light.
 * @param   addrMode - Unicast or Group cast.
 *
 * @return  none
 */
void zllSocSetLevel(uint8_t level, uint16_t time, uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
{
  	uint8_t cmd[] = {
  		0xFE,
  		14,   //RPC payload Len
  		0x29, //MT_RPC_CMD_AREQ + MT_RPC_SYS_APP
  		0x00, //MT_APP_MSG
  		0x0B, //Application Endpoint
  		(dstAddr & 0x00ff),
  		(dstAddr & 0xff00) >> 8,
  		endpoint, //Dst EP
  		(ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL & 0x00ff),
  		(ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL & 0xff00) >> 8,
  		0x07, //Data Len
  		addrMode,
  		0x01, //0x01 ZCL frame control field.  (send to the light cluster only)
  		transSeqNumber++,
  		COMMAND_LEVEL_MOVE_TO_LEVEL,
  		(level & 0xff),
  		(time & 0xff),
  		(time & 0xff00) >> 8,
  		0x00       //FCS - fill in later
  	};
 
    calcFcs(cmd, sizeof(cmd));
 
    write(serialPortFd,cmd,sizeof(cmd));
    tcflush(serialPortFd, TCOFLUSH);
}