Main Content

ZigBee Home Automation Frame Generation and Decoding

This example shows how to generate and decode application-layer frames for the Home Automation application profile [ 1 ] of the ZigBee® specification [ 2 ] using the Communications Toolbox™.

Background

The ZigBee standard [ 2 ] specifies the network (NET or NWK) and application (APP or APL) layers for low-rate wireless personal area networks. These NET- and APP-layer specifications build upon the PHY and MAC specifications of IEEE® 802.15.4™ [ 3 ]. ZigBee devices find application in home automation and sensor networking and are highly relevant to the Internet of Things (IoT) trend.

The ZigBee application layer consists of multiple sub-layers: (i) the application support sublayer (APS), and (ii) the ZigBee cluster library (ZCL). The APS sublayer follows a format that is common for all application profiles and ZigBee clusters (see Clause 2.2.5 in [ 2 ]). The ZCL header follows a format that is common for all clusters (see Clause 2.4 in [ 4 ]). The ZCL payload is used only by some clusters and it follows a cluster-specific format.

Clusters and Frame Captures

Out of all the clusters used in the Home Automation application profile, this example decodes and generates frames for: (i) the On/Off cluster (used by light devices), and (ii) the intruder alarm system (IAS) zone cluster (used by motion sensors) [ 4 ]. The On/Off cluster does not make use of a ZCL payload, but the IAS zone cluster does.

Frames of these clusters have been captured from commercial ZigBee radios enabling home automation, using a USRP® B200-mini radio and the Communications Toolbox Support Package for USRP® radio. ZigBee can employ security either at the network or the application layer. The captured frames employed security at the network layer and were later on decrypted. This example decodes the application layer of the decrypted NET-layer payloads.

load zigbeeAPPCaptures

Decoding APS Frames of Home Automation ZigBee Radios

A zigbee.APSFrameConfig configuration object is used both in generating and decoding ZigBee APS frames. Such objects describe a APS-layer frame and specify its frame type and all applicable properties. The zigbee.APSFrameDecoder function accepts a APS protocol data unit (APDU) in bytes and outputs a zigbee.APSFrameConfig object describing the frame and possibly a ZCL frame in bytes. Clause 2.2.5.1 in [ 2 ] describes the APS frame formats.

Next, the APS sublayer of a captured IAS zone frame is decoded:

[apsConfig,apsPayload] = zigbee.APSFrameDecoder(motionDetectedFrame);
apsConfig
apsConfig = 

  APSFrameConfig with properties:

                FrameType: 'Data'
               APSCounter: 230
    AcknowledgmentRequest: 1

   Addressing:
             DeliveryMode: 'Unicast'
      DestinationEndpoint: '01'
                ClusterID: '0500'
                ProfileID: '0104'
           SourceEndpoint: '01'

   Extended header:
           ExtendedHeader: 0

   Security:
                 Security: 0

Decoding ZCL Header of Home Automation ZigBee Radios

A zigbee.ZCLFrameConfig configuration object is used both in generating and decoding ZigBee ZCL headers. Such objects describe a ZCL-layer frame and specify its frame type and all applicable properties.

The zigbee.ZCLFrameDecoder function accepts a ZCL frame in bytes and outputs a zigbee.ZCLFrameConfig object describing the header and possibly a ZCL payload in bytes. Clause 2.4.1 in [ 4 ] describes the ZCL header frame formats. Note that the ZCL header may either specify a 'Library-wide' or a 'Cluster-specific' command type. In the latter case, the zigbee.ZCLFrameDecoder also needs the cluster ID, which is present in the APS header, in order to decode the cluster-specific command ID into a command type. For example, the next command decodes the ZCL header of a captured IAS zone frame.

[zclConfig,zclPayload] = zigbee.ZCLFrameDecoder( ...
    apsPayload, ...
    apsConfig.ClusterID);
zclConfig
zclConfig = 

  ZCLFrameConfig with properties:

                 FrameType: 'Cluster-specific'
               CommandType: 'Zone Status Change Notification'
            SequenceNumber: 9
       ManufacturerCommand: 0
                 Direction: 'Downlink'
    DisableDefaultResponse: 0

Decoding ZCL Payload of IAS Zone Frame from ZigBee Radio

In contrast to the On/Off cluster, the IAS zone cluster specifies a ZCL payload in addition to the ZCL header. A zigbee.IASZoneFrameConfig configuration object is used both in generating and decoding IAS zone ZCL payloads. Such objects describe an IAS zone payload and all applicable properties. The zigbee.IASZoneFrameDecoder function accepts an IAS zone payload in bytes and outputs a zigbee.IASZoneFrameConfig object describing the IAS zone payload.

iasZoneConfig = zigbee.IASZoneFrameDecoder(zclPayload)
iasZoneConfig = 

  IASZoneFrameConfig with properties:

        CommandType: 'Zone Status Change Notification'
             ZoneID: 0
             Alarm1: 'Not alarmed'
             Alarm2: 'Alarmed'
           Tampered: 0
         LowBattery: 0
    PeriodicReports: 0
     RestoreReports: 1
            Trouble: 0
            ACFault: 0
      BatteryDefect: 0
           TestMode: 0
              Delay: 0

Decoding Motion-Triggered Lighting Automation of ZigBee Radios

A lighting automation has been established for the commercial home-automation ZigBee radios whose frames have been captured and decoded. Specifically, once a motion sensor detects motion, it sends a signal to the ZigBee hub, which in turn sends a signal to a light bulb so that it turns on. When the motion sensor detects that the motion has stopped (e.g., after 10 seconds without motion) it sends a signal to the ZigBee hub, which in turn wirelessly triggers the light bulb to turn off. The following video illustrates the lighting automation.

helperPlaybackVideo('LightingAutomation.mp4',2/5);

The following code decodes the actual frames transmitted between the ZigBee radios. These were captured with a USRP® device (also shown in the video).

apsFrames = ...
{motionDetectedFrame; turnOnFrame; motionStoppedFrame; turnOffFrame};
for idx = 1:length(apsFrames)
    % APS decoding:
    [apsConfig,apsPayload] = zigbee.APSFrameDecoder(apsFrames{idx});
    % ZCL header decoding:
    [zclConfig,zclPayload] = zigbee.ZCLFrameDecoder(apsPayload, ...
        apsConfig.ClusterID);
    zclConfig

    % On-off cluster (does not have ZCL payload)
    onOffClusterID = '0006';
    if strcmp(apsConfig.ClusterID,onOffClusterID)
        fprintf(['Turn light bulb ' lower(zclConfig.CommandType) '.\n']);
    end

    % IAS zone cluster has ZCL payload:
    iasZoneClusterID = '0500';
    if ~isempty(zclPayload) && strcmp(apsConfig.ClusterID,iasZoneClusterID)
        iasConfig = zigbee.IASZoneFrameDecoder(zclPayload)

        if any(strcmp('Alarmed',{iasConfig.Alarm1,iasConfig.Alarm2}))
            fprintf('Motion detected.\n');
        else
            fprintf('Motion stopped.\n');
        end
    end
end
zclConfig = 

  ZCLFrameConfig with properties:

                 FrameType: 'Cluster-specific'
               CommandType: 'Zone Status Change Notification'
            SequenceNumber: 9
       ManufacturerCommand: 0
                 Direction: 'Downlink'
    DisableDefaultResponse: 0


iasConfig = 

  IASZoneFrameConfig with properties:

        CommandType: 'Zone Status Change Notification'
             ZoneID: 0
             Alarm1: 'Not alarmed'
             Alarm2: 'Alarmed'
           Tampered: 0
         LowBattery: 0
    PeriodicReports: 0
     RestoreReports: 1
            Trouble: 0
            ACFault: 0
      BatteryDefect: 0
           TestMode: 0
              Delay: 0

Motion detected.

zclConfig = 

  ZCLFrameConfig with properties:

                 FrameType: 'Cluster-specific'
               CommandType: 'On'
            SequenceNumber: 64
       ManufacturerCommand: 0
                 Direction: 'Uplink'
    DisableDefaultResponse: 0

Turn light bulb on.

zclConfig = 

  ZCLFrameConfig with properties:

                 FrameType: 'Cluster-specific'
               CommandType: 'Zone Status Change Notification'
            SequenceNumber: 10
       ManufacturerCommand: 0
                 Direction: 'Downlink'
    DisableDefaultResponse: 0


iasConfig = 

  IASZoneFrameConfig with properties:

        CommandType: 'Zone Status Change Notification'
             ZoneID: 0
             Alarm1: 'Not alarmed'
             Alarm2: 'Not alarmed'
           Tampered: 0
         LowBattery: 0
    PeriodicReports: 0
     RestoreReports: 1
            Trouble: 0
            ACFault: 0
      BatteryDefect: 0
           TestMode: 0
              Delay: 0

Motion stopped.

zclConfig = 

  ZCLFrameConfig with properties:

                 FrameType: 'Cluster-specific'
               CommandType: 'Off'
            SequenceNumber: 70
       ManufacturerCommand: 0
                 Direction: 'Uplink'
    DisableDefaultResponse: 0

Turn light bulb off.

Generating IAS Zone ZCL Payloads

The zigbee.IASZoneFrameGenerator function accepts a zigbee.IASZoneFrameConfig object describing the IAS zone payload and outputs the payload in bytes. The following code creates two ZCL payloads for this cluster indicating that intrusion has or has not been detected.

iasConfigIntrusion = zigbee.IASZoneFrameConfig('Alarm2','Alarmed');
zclPayloadIntrusion = zigbee.IASZoneFrameGenerator(iasConfigIntrusion);

iasConfigNoIntrusion = zigbee.IASZoneFrameConfig('Alarm2','Not alarmed');
zclPayloadNoIntrusion = zigbee.IASZoneFrameGenerator(iasConfigNoIntrusion);

Generating ZCL Frames

The zigbee.ZCLFrameGenerator function accepts a zigbee.ZCLFrameConfig object describing the frame, and optionally a ZCL payload in bytes (two-characters), and outputs the ZCL frame in bytes. The following code generates ZCL frames for the On/Off cluster (no payload) and the IAS zone cluster (payload needed).

% IAS Zone Cluster
zclConfigIntrusion = zigbee.ZCLFrameConfig( ...
    'FrameType','Cluster-specific', ...
    'CommandType','Zone Status Change Notification', ...
    'SequenceNumber',1,'Direction','Downlink');
zclFrameIntrusion = zigbee.ZCLFrameGenerator(zclConfigIntrusion, ...
    zclPayloadIntrusion);

% On/Off Cluster
zclConfigOn = zigbee.ZCLFrameConfig( ...
    'FrameType','Cluster-specific', ...
    'CommandType','On', ...
    'SequenceNumber',2,'Direction','Uplink');
zclFrameOn = zigbee.ZCLFrameGenerator(zclConfigOn);

Generating APS Frames

The zigbee.APSFrameGenerator function accepts a zigbee.APSFrameConfig object describing the frame, and optionally a APS payload (ZCL-layer frame) in bytes (two-characters), and outputs the APS frame in bytes. The following code illustrates how to generate APS frames for the ZCL frames created in the previous section.

% IAS Zone Cluster
apsConfigIntrusion = zigbee.APSFrameConfig( ...
    'FrameType','Data', ...
    'ClusterID',iasZoneClusterID, ...
    'ProfileID',zigbee.profileID('Home Automation'), ...
    'APSCounter',1, ...
    'AcknowledgmentRequest',true);
apsFrameIntrusion = zigbee.APSFrameGenerator(apsConfigIntrusion, ...
    zclFrameIntrusion);

% On/Off cluster
apsConfigOn = zigbee.APSFrameConfig('FrameType','Data', ...
    'ClusterID',onOffClusterID, ...
    'ProfileID',zigbee.profileID('Home Automation'), ...
    'APSCounter',2, ...
    'AcknowledgmentRequest',true);
apsFrameOn = zigbee.APSFrameGenerator(apsConfigOn,zclFrameOn);

Further Exploration

The example uses these undocumented utilities. The API and functionality of undocumented utilities may change in the future. To view the source code of the utilities, use the edit function.

  • zigbee.APSFrameConfig, zigbee.APSFrameGenerator, zigbee.APSFrameDecoder

  • zigbee.ZCLFrameConfig, zigbee.ZCLFrameGenerator, zigbee.ZCLFrameDecoder

  • zigbee.IASZoneFrameConfig, zigbee.IASZoneFrameGenerator, zigbee.IASZoneFrameDecoder

Selected Bibliography

  1. ZigBee Alliance, ZigBee Home Automation Public Application Profile, revision 29, v. 1.2, Jun. 2013.

  2. ZigBee Alliance, ZigBee Specification Document 053474r17, 2007

  3. IEEE 802.15.4-2011 - IEEE Standard for Local and Metropolitan Area Networks--Part 15.4: Low-Rate Wireless Personal Area Networks (LR-WPANs)

  4. ZigBee Alliance, ZigBee Cluster Library Specification, Revision 6, Jan. 2016.

Related Topics