Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...


The GatewayAPI aims to abstract away the underlying protocol, i.e Zigbee, but there are instances where clients/users will want direct access to the underlying protocol. This document will describe how to send ZCL/ Unicast, Broadcast Messages, and Multicast Messages. This document will describe the message format of the request and response.


API

<todo incorrect writeAttribute parameters>


The ZigBeeDevice

  • CompletableFuture<Property> readAttribute(int clusterId, int attributeId)
  • CompletableFuture<Property> readAttribute(int clusterId, int attributeId, int manufacturerCode, boolean isServer)
  • CompletableFuture<Property> writeAttribute(int clusterId, int attributeId, short dataType, byte[] value)
  • CompletableFuture<Property> writeAttribute(int clusterId, int attributeId, short dataType, byte[] value, int manufacturerCode, boolean isServer)
  • CompletableFuture<Property> sendZclCommand(short commandId, byte[] payload, int clusterId)
  • CompletableFuture<Property> sendZclCommand(short commandId, byte[] payload, int clusterId)
  • CompletableFuture<Property> sendZclCommand(short commandID, byte[] payload, int clusterId, int manufacturerCode, boolean isServer, boolean isClusterSpecific, boolean requiresResponse)
  • CompletableFuture<Collection<Property>> sendZclMulticastCommand(int groupID, short commandID, byte[] payload, int clusterId, int manufacturerCode, boolean isServer, boolean isClusterSpecific, boolean requiresResponse)
  • CompletableFuture<Collection<Property>> sendZclMulticastCommand(String broadcastAddress, short commandID, byte[] payload, int clusterId, int manufacturerCode, boolean isServer, boolean isClusterSpecific, boolean requiresResponse)

...

Code Block
languagejava
titleWrite Attribute Example

ZigBeeDevice device = ...

int clusterID = 0x0000 // Basic Cluster
int attributeID = 0x0075 // random attribute with read/write access control
short dataType = 0x21 // UInt16
byte[] value = new byte[]{(btye)0x34, (byte)0x12}; // writing the value 0x1234, Little-Endian

CompletableFuture<Property> results = device.writeAttribute(clusterID, attributeID, dataType, value)
results.whenComplete((propertyResult, error) -> {
	if (error != null) {
		// handle error of computation
	} else {
		String jsonResults = propertyResult.getValue()
		...
		// parse results
		...
	}
});

...

Code Block
languagejs
[
    {
        "gatewayApiVersion":"2.0.14-SNAPSHOT",
        "protocolName":"zigbee",
        "protocolVersion":3,
        "messageType":"zcl_response",
        "message":{
            "sourceNode":"0x4544",
            "sourceEndpoint":"0x01",
            "localEndpoint":"0x01",
            "clusterId":"0x0000",
            "encryption":"0x00",
            "frameControl":"0x18",
            "manufacturerCode":"0x0000",
            "transactionNum":"0x11",
            "commandId":"0x04",
            "payload":"0x00" //success
        }
    }
]


Unicast

...

languagejs
titleUnicast Example

Broadcast

...

titleBroadcast Example

Multicast

...

languagejava
titleMulticast Example

...

The ZCL Unicast method is a prime candidate for sending one command to a targeted node/end device. 

Example of Sending the Add Group Command

Here is an example of sending the add group command (0x00) to a node with the groups server cluster (0x0004)

Code Block
languagejava
ZigbeeDevice device = ...

short commandId = 0x02;
byte[] payload = new byte[]{(byte)0x00, (byte)0x01}; // add group id of 0x0100
int clusterId = 0x0004; // group cluster
int manufacturerCode = 0;
boolean isServer = true; // client to server (end device)
boolean isClusterSpecific = true;
boolean requiresResponse = true;

CompletableFuture<Property> results = device.sendZclCommand(commandId, payload, clusterId, manufacturerCode, isServer, isClusterSpecific, requiresResponse)
results.whenComplete((propertyResult, error) -> {
	if (error != null) {
		// handle error of computation
	} else {
		String jsonResults = propertyResult.getValue()
		...
		// parse results
		...
	}
});

The Add Group Command has a response:

Code Block
[
    {
        "gatewayApiVersion":"2.0.14-SNAPSHOT",
        "protocolName":"zigbee",
        "protocolVersion":3,
        "messageType":"zcl_response",
        "message":{
            "sourceNode":"0x4544",
            "sourceEndpoint":"0x01",
            "localEndpoint":"0x01",
            "clusterId":"0x0004",
            "encryption":"0x00",
            "frameControl":"0x19",
            "manufacturerCode":"0x0000",
            "transactionNum":"0x21",
            "commandId":"0x00", // Add group response commandid
            "payload":"0x000001" // status - 0x00 - group id - 0x0100
        }
    }
]

If requireResponse = false, then the method will return a default response

Code Block
[
    {
        "gatewayApiVersion":"2.0.13",
        "protocolName":"zigbee",
        "protocolVersion":3,
        "messageType":"default_response",
        "message":{
            "status":"0x00"
        }
    }
]


Example of Sending Toggle Command (0x02)

Here is an example of sending a toggle command (0x02) to the end device containing the On/Off Server Cluster (0x0006).

Code Block
languagejava
// example, toggle command for on/off

ZigBeeDevice device = ...

short commandId = 0x02;
byte[] payload = new byte[0]; // no payload for toggle
int clusterId = 0x0006; // on off cluster
int manufacturerCode = 0;
boolean isServer = true; // client to server (end device)
boolean isClusterSpecific = true;
boolean requiresResponse = false;

CompletableFuture<Property> results = device.sendZclCommand(commandId, payload, clusterId, manufacturerCode, isServer, isClusterSpecific, requiresResponse)
results.whenComplete((propertyResult, error) -> {
	if (error != null) {
		// handle error of computation
	} else {
		String jsonResults = propertyResult.getValue()
		...
		// parse results
		...
	}
});


The response if requiresResponse = true or false,

Code Block
languagejs
titleUnicast Example
[
    {
        "gatewayApiVersion":"2.0.13",
        "protocolName":"zigbee",
        "protocolVersion":3,
        "messageType":"default_response",
        "message":{
            "status":"0x00"
        }
    }
]


The toggle command does not generate a response therefore, even if we set requiresResponse = true, it will still generate a default response.


Broadcast

Broadcast Addresses

  • 0xFF - All Addresses
  • 0xFD - Non - sleepy devices
  • 0xFC - all routers and coordinator

Any other value will default to 0xFD

Example of Sending the Add Group Command

This example will be broadcasting to two devices

Code Block
titleBroadcast Example
// example add group command

ZigBeeDevice device = ...
String broadcastAddress = "0xFD";
short commandId = 0x02;
byte[] payload = new byte[0]; // no payload for toggle
int clusterId = 0x0006; // on off cluster
int manufacturerCode = 0;
boolean isServer = true; // client to server (end device)
boolean isClusterSpecific = true;
boolean requiresResponse = true;

CompletableFuture<Collection<Property>> results = device.sendZclBroadcastCommand(broadcastAddresscommandId, payload, clusterId, manufacturerCode, isServer, isClusterSpecific, requiresResponse)
results.whenComplete((properties, error) -> {
	if (error != null) {
		// handle error of computation
	} else {
		for (Property property : properties) {
			String json = property.getValue();
			
			// parse json and handle result
		}
	}
});


Each Property will have the following JSON results.

Code Block
// 1st property in properties collection 
{
    "gatewayApiVersion":"2.0.13",
    "protocolName":"zigbee",
    "protocolVersion":3,
    "messageType":"zcl_response",
    "message":{
        "sourceNode":"0x1FAD",
        "sourceEndpoint":"0x01",
        "localEndpoint":"0x01",
        "clusterId":"0x0004",
        "encryption":"0x00",
        "frameControl":"0x19",
        "manufacturerCode":"0x0000",
        "transactionNum":"0x3E",
        "commandId":"0x00",
        "payload":"0x000100"
    }
}

// 2nd property in properties collection
{
    "gatewayApiVersion":"2.0.13",
    "protocolName":"zigbee",
    "protocolVersion":3,
    "messageType":"zcl_response",
    "message":{
        "sourceNode":"0x4544",
        "sourceEndpoint":"0x01",
        "localEndpoint":"0x01",
        "clusterId":"0x0004",
        "encryption":"0x00",
        "frameControl":"0x19",
        "manufacturerCode":"0x0000",
        "transactionNum":"0x3E",
        "commandId":"0x00",
        "payload":"0x000100"
    }
}


if requiresResponse = false:

Code Block
{
    "gatewayApiVersion":"2.0.14-SNAPSHOT",
    "protocolName":"zigbee",
    "protocolVersion":3,
    "messageType":"default_response",
    "message":{
        "status":"0x00"
    }
}

Example of Sending Toggle Command (0x02)

Code Block

// example, toggle command for on/off

ZigBeeDevice device = ...
String broadcastAddress = "0xFD";
short commandId = 0x02;
byte[] payload = new byte[0]; // no payload for toggle
int clusterId = 0x0006; // on off cluster
int manufacturerCode = 0;
boolean isServer = true; // client to server (end device)
boolean isClusterSpecific = true;
boolean requiresResponse = false;

CompletableFuture<Collection<Property>> results = device.sendZclBroadcastCommand(broadcastAddresscommandId, payload, clusterId, manufacturerCode, isServer, isClusterSpecific, requiresResponse)
results.whenComplete((properties, error) -> {
	if (error != null) {
		// handle error of computation
	} else {
		for (Property property : properties) {
			String json = property.getValue();
			
			// parse json and handle result
		}
	}
});


The response will be a single property in the collection with a default response indicating the message has been sent

Code Block
// property value:
{
    "gatewayApiVersion":"2.0.14-SNAPSHOT",
    "protocolName":"zigbee",
    "protocolVersion":3,
    "messageType":"default_response",
    "message":{
        "status":"0x00"
    }
}


Multicast

Sending The Toggle Command

Code Block
languagejava
titleMulticast Example

// example add group command

ZigBeeDevice device = ...
int groupID = 1;
short commandId = 0x02;
byte[] payload = new byte[0]; // no payload for toggle
int clusterId = 0x0006; // on off cluster
int manufacturerCode = 0;
boolean isServer = true; // client to server (end device)
boolean isClusterSpecific = true;
boolean requiresResponse = true;

CompletableFuture<Collection<Property>> results = device.sendZclMulticastCommand(groupID, payload, clusterId, manufacturerCode, isServer, isClusterSpecific, requiresResponse)
results.whenComplete((properties, error) -> {
	if (error != null) {
		// handle error of computation
	} else {
		for (Property property : properties) {
			String json = property.getValue();
			
			// parse json and handle result
		}
	}
});


The response from being broadcasted to 2 nodes/end-devices:

Code Block
// 1st property in properties collection 
{
    "gatewayApiVersion":"2.0.13",
    "protocolName":"zigbee",
    "protocolVersion":3,
    "messageType":"zcl_response",
    "message":{
        "sourceNode":"0x1FAD",
        "sourceEndpoint":"0x01",
        "localEndpoint":"0x01",
        "clusterId":"0x0004",
        "encryption":"0x00",
        "frameControl":"0x19",
        "manufacturerCode":"0x0000",
        "transactionNum":"0x3E",
        "commandId":"0x00",
        "payload":"0x000100"
    }
}

// 2nd property in properties collection
{
    "gatewayApiVersion":"2.0.13",
    "protocolName":"zigbee",
    "protocolVersion":3,
    "messageType":"zcl_response",
    "message":{
        "sourceNode":"0x4544",
        "sourceEndpoint":"0x01",
        "localEndpoint":"0x01",
        "clusterId":"0x0004",
        "encryption":"0x00",
        "frameControl":"0x19",
        "manufacturerCode":"0x0000",
        "transactionNum":"0x3E",
        "commandId":"0x00",
        "payload":"0x000100"
    }
}


Failed Requests

There are differing failures when it comes to ZCL:

  • Failed to send to target node → Default Response
  • Failure in target node processing command → ZCL Response (Default Response, if requireResponse = false)

Default Response

If there is an error with the request, you will get a default response with a status code.request, you will get a default response with a status code. This means the request failed to be sent in some way. This usually means that the message failed to be sent, or if requiresResponse = false, a default response will be sent to the user/client instead of a ZCL Response

e.g Default Response, Status Code 0x01 (Failure). 

...

Code Block
languagejs
titleFailed Request
[
    {
        "gatewayApiVersion":"2.0.13",
        "protocolName":"zigbee",
        "protocolVersion":3,
        "messageType":"default_response",
        "message":{
            "status":"0x01"
        }
    }
]


ZCL Response

For certain situations, you could receive a ZCL Response with a failure statusZCL Response with a failure status. This is an error code from the target device. You must inspect the frame control, command id, and payload to decipher the meaning of this response. Please see the ZCL Specification for more details for that command.

Code Block
[
    {
        "gatewayApiVersion":"2.0.14",
        "protocolName":"zigbee",
        "protocolVersion":3,
        "messageType":"zcl_response",
        "message":{
            "sourceNode":"0x4544",
            "sourceEndpoint":"0x01",
            "localEndpoint":"0x01",
            "clusterId":"0x0000",
            "encryption":"0x00",
            "frameControl":"0x18",
            "manufacturerCode":"0x0000",
            "transactionNum":"0x12",
            "commandId":"0x04", // write command
            "payload":"0x869900" // contains status code 0x86 - unsupported attribute
        }- 
    }
]


Status Codes

...

<todo list status codes here>

and Data Types

<todo list data types here>

They can be found in the Zigbee Specification References