%% ZigBee Light Link Frame Generation and Decoding
% This example shows how to generate and decode frames of the ZigBee(R)
% Light Link application profile [ <#20 1> ] using the Communications
% Toolbox(TM) Library for ZigBee and UWB.

% Copyright 2017-2021 The MathWorks, Inc.

%% Background
% The ZigBee standard [ <#20 2> ] specifies network (NET or NWK) and
% application (APP or APL) layers of low-rate wireless personal area
% networks (LR-WPANs). These NET- and APP-layer specifications build upon
% the PHY and MAC specifications of IEEE(R) 802.15.4(TM) [ <#20 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). 
%
% <<zigbeeFrameFormat.png>>
%
% The APS and ZCL *headers* follow a format that is common for all
% application profiles and ZigBee clusters (see Clauses 2.2.5 in [ <#20 2>
% ] and 2.4 in [ <#20 4> ], respectively). The ZCL *payload* is used only
% by some clusters and it follows a cluster-specific format. The generic
% APS and ZCL header generation and decoding is illustrated in the
% <docid:comm_ug#example-zigbeeHomeAutomationExample ZigBee Home Automation
% Frame Generation and Decoding> example. This example illustrates the
% cluster-specific generation and decoding of *ZigBee Light Link ZCL
% payloads*.

%% Clusters and Commands
% Out of the 7 clusters specified in the Light Link application profile [
% <#20 1> ], this example generates and decodes frames for the following
% clusters:
%
% # *Identify cluster*: This cluster sets a device into identification mode
% (e.g., flashing a light). This example illustrates frame generation and
% decoding for the *Identify command* (described in Clause 3.5 of [ <#20 4>
% ]).
% # *Color Control cluster*: This cluster changes the color of a lighting
% device. This example illustrates frame generation and decoding for the
% *Move to Color command* (described in Clause 5.2 of [ <#20 4> ]).
% # *Level Control* cluster: This cluster modifies the level of a device,
% e.g., the intensity of a light bulb, how closed a door is, or the
% intensity of a heater. This example illustrates frame generation and
% decoding for the *Move to Level command* (described in Clause 3.10 of [
% <#20 4> ]).
% # *Scenes cluster*: The scenes cluster sets up and recalls scenes
% (i.e., sets of stored attribute values for other clusters in the same
% device). This example illustrates frame generation and decoding for the
% *View Scene command* (described in Clause 3.7 of [ <#20 4> ]).
% # *Group cluster*: This cluster manages groups of devices, e.g., by
% creating or removing a group, or by discovering group membership. This
% example illustrates frame generation and decoding for the *Add group
% command* (described in Clause 3.6 of [ <#20 4> ]).
%
% In addition to the illustrated commands, this example provides an
% implementation for generating and decoding frames for all commands of the
% five mentioned clusters (see <#19 Further Exploration> for a complete list).

%% Generating and Decoding ZCL Payload of Identify Cluster
% A <matlab:edit('zigbee.IdentifyFrameConfig') zigbee.IdentifyFrameConfig>
% configuration object is used both in generating and decoding ZCL payloads
% of the Identify cluster. Such objects describe an Identify cluster
% payload and all applicable properties. The
% <matlab:edit('zigbee.IdentifyFrameGenerator')
% zigbee.IdentifyFrameGenerator> function accepts a
% <matlab:edit('zigbee.IdentifyFrameConfig') zigbee.IdentifyFrameConfig>
% object describing the Identify cluster payload and outputs the generated
% payload in bytes. The following code creates a ZCL payload for a command
% asking a device to identify for 4 seconds.

% Creation of configuration object for Identify cluster
identifyConfigTx = zigbee.IdentifyFrameConfig('CommandType', 'Identify', ...
                                              'IdentifyTime', 4);

% Frame generation (ZCL payload) for Identify cluster 
identifyPayload = zigbee.IdentifyFrameGenerator(identifyConfigTx);

%%
% The <matlab:edit('zigbee.IdentifyFrameDecoder')
% zigbee.IdentifyFrameDecoder> function accepts the command name and a
% Identify cluster payload in bytes and outputs a
% <matlab:edit('zigbee.IdentifyFrameConfig') zigbee.IdentifyFrameConfig>
% object describing the Identify cluster payload. The command name is
% retrieved from the decoding of the ZCL header. See section 'Decoding ZCL
% Header of Home Automation ZigBee Radios' in the
% <docid:comm_ug#example-zigbeeHomeAutomationExample ZigBee Home Automation
% Frame Generation and Decoding> example.

identifyConfigRx = zigbee.IdentifyFrameDecoder('Identify', identifyPayload)

%% 
% The following code visualizes a "software bulb" that illustrates the
% identification effect specified in the received frame.

bulb = plotBulb('white');
zigbeeIdentifyBulb(bulb, identifyConfigRx.IdentifyTime);
close(bulb);

%% Generating and Decoding ZCL Payload of Color Control Cluster
% A <matlab:edit('zigbee.ColorControlFrameConfig')
% zigbee.ColorControlFrameConfig> configuration object is used both in
% generating and decoding ZCL payloads of the Color Control cluster. Such
% objects describe a Color Control cluster payload and all applicable
% properties. The <matlab:edit('zigbee.ColorControlFrameGenerator')
% zigbee.ColorControlFrameGenerator> function accepts a
% <matlab:edit('zigbee.ColorControlFrameConfig')
% zigbee.ColorControlFrameConfig> object describing the Color Control
% cluster payload and outputs the generated payload in bytes. The following
% code generates a Color Control cluster payload that instructs a lighting
% device to progressively change its current color (red) to a different
% value (green) within 50 deciseconds (i.e., 5 seconds). Color is described
% in terms of _x_, _y_ values according to the CIE 1931 color space
% established by the International Commission on Illumination (CIE) [ <#20
% 5> ].

bulb = plotBulb('red');

%%

% Creation of configuration object for Color Control cluster 
colorCtrlConfigTx = zigbee.ColorControlFrameConfig('CommandType', 'Move to Color', ...
                                                   'ColorX', 16384, 'ColorY', 39322, 'Time', 50);

% Frame generation (ZCL payload) for Color Control cluster
colorControlPayload = zigbee.ColorControlFrameGenerator(colorCtrlConfigTx);

%%
% The <matlab:edit('zigbee.ColorControlFrameDecoder')
% zigbee.ColorControlFrameDecoder> function accepts the command name and a
% Color Control cluster payload in bytes and outputs a
% <matlab:edit('zigbee.ColorControlFrameConfig')
% zigbee.ColorControlFrameConfig> object describing the Color Control
% cluster payload. The command name is retrieved from the decoding of the
% ZCL header. See section 'Decoding ZCL Header of Home Automation ZigBee
% Radios' in the <docid:comm_ug#example-zigbeeHomeAutomationExample ZigBee
% Home Automation Frame Generation and Decoding> example.

colorCtrlConfigRx = zigbee.ColorControlFrameDecoder('Move to Color', colorControlPayload)

%% 
% The following command uses a "software bulb" to visualize the Color
% Control effect specified in the received frame. Specifically, the color
% of a bulb progressively changes from red to green within 5 seconds.

zigbeeMoveBulbColor(bulb, colorCtrlConfigRx.ColorX, colorCtrlConfigRx.ColorY, colorCtrlConfigRx.Time);

%%
% Next, the same effect occurs on a different color trajectory (from green
% to violet).
colorCtrlConfigTx2 = zigbee.ColorControlFrameConfig('CommandType', 'Move to Color', ...
                                                   'ColorX',  19661, 'ColorY', 6554, 'Time', 50);
colorControlPayload2 = zigbee.ColorControlFrameGenerator(colorCtrlConfigTx2);
colorCtrlConfigRx2 = zigbee.ColorControlFrameDecoder('Move to Color', colorControlPayload2);
zigbeeMoveBulbColor(bulb, colorCtrlConfigRx2.ColorX, colorCtrlConfigRx2.ColorY, colorCtrlConfigRx2.Time);

pause(1.5);

%% Generating and Decoding ZCL Payload of Level Control Cluster
% A <matlab:edit('zigbee.LevelControlFrameConfig')
% zigbee.LevelControlFrameConfig> configuration object is used both in
% generating and decoding Level Control cluster ZCL payloads. Such objects
% describe a Level Control cluster payload and all applicable properties. The
% <matlab:edit('zigbee.LevelControlFrameGenerator')
% zigbee.LevelControlFrameGenerator> function accepts a
% <matlab:edit('zigbee.LevelControlFrameConfig')
% zigbee.LevelControlFrameConfig> object describing the Level Control
% cluster payload and outputs the generated payload in bytes. The following code
% creates a Level Control cluster payload that instructs a device to change
% its current level to the specified value.

% Creation of Level Control cluster configuration object
levelCtrlConfigTx = zigbee.LevelControlFrameConfig('CommandType', 'Move to Level', ...
                                                   'Level', 20, 'TransitionTime', 1);

% Level Control cluster frame generation (ZCL payload)
levelControlPayload = zigbee.LevelControlFrameGenerator(levelCtrlConfigTx);

%%
% The <matlab:edit('zigbee.LevelControlFrameDecoder')
% zigbee.LevelControlFrameDecoder> function accepts the command name and a
% Level Control cluster payload in bytes and outputs a
% zigbee.LevelControlFrameConfig object describing the Level Control
% cluster payload. The command name is retrieved from the decoding of the
% ZCL header. See section 'Decoding ZCL Header of Home Automation ZigBee
% Radios' in the <docid:comm_ug#example-zigbeeHomeAutomationExample ZigBee
% Home Automation Frame Generation and Decoding> example.

levelCtrlConfigRx = zigbee.LevelControlFrameDecoder('Move to Level', levelControlPayload)

%%
% While the Level Control cluster can be used to regulate the intensity of
% a light, the Color Control cluster leaves it to the Level Control cluster
% to control the *luminance* of a lighting device's color. The following
% example uses the received Level Control frame to increase the luminance
% level of a light bulb.

zigbeeMoveBulbColor(bulb, colorCtrlConfigRx2.ColorX, colorCtrlConfigRx2.ColorY, 1, levelCtrlConfigRx.Level);

%% Generating and Decoding ZCL Payload of Scenes Cluster
% A <matlab:edit('zigbee.SceneFrameConfig') zigbee.SceneFrameConfig>
% configuration object is used both in generating and decoding Scenes
% cluster ZCL payloads. Such objects describe a Scenes cluster payload and
% all applicable properties. The <matlab:edit('zigbee.ScenesFrameGenerator')
% zigbee.ScenesFrameGenerator> function accepts a
% <matlab:edit('zigbee.ScenesFrameConfig') zigbee.ScenesFrameConfig> object
% describing the Scenes cluster payload and outputs the generated payload in bytes.
% The following code generates a Scenes cluster payload that requests a
% device to transmit a different frame (View Scene Response) describing a
% scene.

% Creation of Scenes cluster configuration object
scenesConfigTx = zigbee.ScenesFrameConfig('CommandType', 'View Scene', ...
                                          'GroupID', '1234', 'SceneID', '56');

% Scenes cluster frame generation (ZCL payload)
scenesPayload = zigbee.ScenesFrameGenerator(scenesConfigTx);

%%
% The <matlab:edit('zigbee.SceneFrameDecoder') zigbee.SceneFrameDecoder>
% function accepts the command name and a Scenes cluster payload in bytes
% and outputs a zigbee.SceneFrameConfig object describing the Scenes
% cluster payload. The command name is retrieved from the decoding of the
% ZCL header. See section 'Decoding ZCL Header of Home Automation ZigBee
% Radios' in the <docid:comm_ug#example-zigbeeHomeAutomationExample ZigBee
% Home Automation Frame Generation and Decoding> example.

scenesConfigRx = zigbee.ScenesFrameDecoder('View Scene', scenesPayload)


%% Generating and Decoding ZCL Payload of Groups Cluster
% A <matlab:edit('zigbee.GroupFrameConfig') zigbee.GroupFrameConfig>
% configuration object is used both in generating and decoding Groups
% cluster ZCL payloads. Such objects describe a Groups cluster payload and
% all applicable properties. The <matlab:edit('zigbee.GroupsFrameGenerator')
% zigbee.GroupsFrameGenerator> function accepts a
% <matlab:edit('zigbee.GroupsFrameConfig') zigbee.GroupsFrameConfig>
% object describing the Groups cluster payload and outputs the generated payload in bytes.
% The following code creates a Groups cluster payload that instructs a
% device to add the specified group to its Group table.

% Creation of Groups cluster configuration object
groupsConfigTx = zigbee.GroupsFrameConfig('CommandType', 'Add group', ...
                        'GroupName', 'Dining Hall', 'GroupID', '1234');

% Groups cluster frame generation (ZCL payload)
groupsPayload = zigbee.GroupsFrameGenerator(groupsConfigTx);

%%
% The <matlab:edit('zigbee.GroupFrameDecoder') zigbee.GroupFrameDecoder>
% function accepts the command name and a Groups cluster payload in bytes
% and outputs a zigbee.GroupFrameConfig object describing the Groups
% cluster payload. The command name is retrieved from the decoding of the
% ZCL header. See section 'Decoding ZCL Header of Home Automation ZigBee
% Radios' in the <docid:comm_ug#example-zigbeeHomeAutomationExample ZigBee
% Home Automation Frame Generation and Decoding> example.

groupsConfigRx = zigbee.GroupsFrameDecoder('Add group', groupsPayload)

%% Wireshark Decoding
% The generated frames can be converted to a PCAP format, which can be
% analyzed and visualized with Wireshark [ <#20 6> ]. This process can
% serve as an additional verification step advocating that the
% Communications Toolbox Library for the ZigBee Protocol generates
% and decodes frames in a standard-compliant manner.
%
% The PCAP file needs the ZCL payloads to be enclosed with headers from all
% other layers and sublayers (MAC, NET, APS, ZCL). The following commands
% generate a PCAP file, for the ZCL payloads generated in this example,
% that can be loaded with Wireshark.

% ZLL profile ID
zllProfileID = zigbee.profileID('Light Link');

payloadsWithInfo(1) = struct('Payload',   identifyPayload,       'ProfileID',   zllProfileID, ...
                             'ClusterSpecific', true,            'ClusterID',   zigbee.clusterID('Identify'),       'CommandType', 'Identify',      'Direction', 'Uplink');
payloadsWithInfo(2) = struct('Payload',   colorControlPayload,   'ProfileID',   zllProfileID, ...
                             'ClusterSpecific', true,            'ClusterID',   zigbee.clusterID('Color Control'),  'CommandType', 'Move to Color', 'Direction', 'Uplink');
payloadsWithInfo(3) = struct('Payload',   levelControlPayload,   'ProfileID',   zllProfileID, ...
                             'ClusterSpecific', true,            'ClusterID',   zigbee.clusterID('Level Control'),  'CommandType', 'Move to Level', 'Direction', 'Uplink');
payloadsWithInfo(4) = struct('Payload',   scenesPayload,         'ProfileID',   zllProfileID, ...
                             'ClusterSpecific', true,            'ClusterID',   zigbee.clusterID('Scenes'),         'CommandType', 'View Scene',    'Direction', 'Uplink');
payloadsWithInfo(5) = struct('Payload',   groupsPayload,         'ProfileID',   zllProfileID, ...
                             'ClusterSpecific', true,            'ClusterID',   zigbee.clusterID('Groups'),         'CommandType', 'Add group',     'Direction', 'Uplink');

% Add headers from other layers/sublayers:
MPDUs = zigbeeAddProtocolHeaders(payloadsWithInfo);

% Export MPDUs to a PCAP format
zigbeeExportToPcap(MPDUs, 'zigbeeLightLink.pcap');

% Open PCAP file with Wireshark

%% Further Exploration
% You can further explore the following generator and decoding functions,
% as well as the configuration object:
%
% * <matlab:edit('zigbee.APSFrameConfig') zigbee.APSFrameConfig>, <matlab:edit('zigbee.APSFrameGenerator') zigbee.APSFrameGenerator>, <matlab:edit('zigbee.APSFrameDecoder') zigbee.APSFrameDecoder>
% * <matlab:edit('zigbee.ZCLFrameConfig') zigbee.ZCLFrameConfig>, <matlab:edit('zigbee.ZCLFrameGenerator') zigbee.ZCLFrameGenerator>, <matlab:edit('zigbee.ZCLFrameDecoder') zigbee.ZCLFrameDecoder>
% * <matlab:edit('zigbee.IdentifyFrameConfig') zigbee.IdentifyFrameConfig>, <matlab:edit('zigbee.IdentifyFrameGenerator') zigbee.IdentifyFrameGenerator>, <matlab:edit('zigbee.IdentifyFrameDecoder') zigbee.IdentifyFrameDecoder>
% * <matlab:edit('zigbee.ColorControlFrameConfig') zigbee.ColorControlFrameConfig>, <matlab:edit('zigbee.ColorControlFrameGenerator') zigbee.ColorControlFrameGenerator>, <matlab:edit('zigbee.ColorControlFrameDecoder') zigbee.ColorControlFrameDecoder>
% * <matlab:edit('zigbee.LevelControlFrameConfig') zigbee.LevelControlFrameConfig>, <matlab:edit('zigbee.LevelControlFrameGenerator') zigbee.LevelControlFrameGenerator>, <matlab:edit('zigbee.LevelControlFrameDecoder') zigbee.LevelControlFrameDecoder>
% * <matlab:edit('zigbee.ScenesFrameConfig') zigbee.ScenesFrameConfig>, <matlab:edit('zigbee.ScenesFrameGenerator') zigbee.ScenesFrameGenerator>, <matlab:edit('zigbee.ScenesFrameDecoder') zigbee.ScenesFrameDecoder>
% * <matlab:edit('zigbee.GroupsFrameConfig') zigbee.GroupsFrameConfig>, <matlab:edit('zigbee.GroupsFrameGenerator') zigbee.GroupsFrameGenerator>, <matlab:edit('zigbee.GroupsFrameDecoder') zigbee.GroupsFrameDecoder>
%
% In addition to the commands illustrated in this example, the offered
% implementation also supports the commands listed in the following table. The commands
% listed in the middle column can be exported to a PCAP file that can be
% analyzed with Wireshark.
%
% <<zigbeeLightLinkTable.png>>

%% Selected Bibliography
% # ZigBee Alliance, ZigBee Light Link Standard, v. 1.0, April 5th, 2012.
% # ZigBee Alliance, ZigBee Specification Document 053474r17, 2007
% # IEEE 802.15.4-2011 - IEEE Standard for Local and metropolitan area
% networks--Part 15.4: Low-Rate Wireless Personal Area Networks (LR-WPANs)
% # ZigBee Alliance, ZigBee Cluster Library Specification, Revision 6, Jan. 2016.
% # CIE 1931 Color Space. Commission Internationale de l'Eclairage Proceedings. 
% Cambridge University Press, Cambridge
% # Wireshark software: https://www.wireshark.org/

displayEndOfDemoMessage(mfilename)
