.. _z-stack-overview:

|STACK| Overview
$$$$$$$$$$$$$$$$$


Introduction
============

Purpose
-------

This document describes basic concepts of Zigbee mesh networks. This is a Zigbee 
PRO 2023 (R23) certified stack for the Zigbee and Zigbee PRO stack profiles.  
For a more complete |STACK|\ |trade| Release description along with stack 
settings pertaining to Texas Instruments devices, please refer to the |ZBOSS_UG|.

Definitions, Abbreviations and Acronyms
---------------------------------------

+--------------+-----------------------------------------------+
| **Term**     | **Definition**                                |
+==============+===============================================+
| AF           | Application Framework                         |
+--------------+-----------------------------------------------+
| AES          | Advanced Encryption Standard                  |
+--------------+-----------------------------------------------+
| AIB          | APS Information Base                          |
+--------------+-----------------------------------------------+
| API          | Application Programming Interface             |
+--------------+-----------------------------------------------+
| APS          | Application Support Sub-Layer                 |
+--------------+-----------------------------------------------+
| APSDE        | APS Date Entity                               |
+--------------+-----------------------------------------------+
| APSME        | APS Management Entity                         |
+--------------+-----------------------------------------------+
| BDB          | Base Device Behavior                          |
+--------------+-----------------------------------------------+
| CCM\*        | Enhanced counter with CBC-MAC mode of         |
|              | operation                                     |
+--------------+-----------------------------------------------+
| EPID         | Extended PAN ID                               |
+--------------+-----------------------------------------------+
| GP           | Green Power                                   |
+--------------+-----------------------------------------------+
| GPD          | Green Power Device                            |
+--------------+-----------------------------------------------+
| MSG          | Message                                       |
+--------------+-----------------------------------------------+
| MT           | Zigbee’s Monitor and Test Layer               |
+--------------+-----------------------------------------------+
| NIB          | Network Information Base                      |
+--------------+-----------------------------------------------+
| NWK          | Network                                       |
+--------------+-----------------------------------------------+
| OTA          | Over-the-Air                                  |
+--------------+-----------------------------------------------+
| PAN          | Personal Area Network                         |
+--------------+-----------------------------------------------+
| RSSI         | Received Signal Strength Indication           |
+--------------+-----------------------------------------------+
| TC           | Trust Center                                  |
+--------------+-----------------------------------------------+
| TCLK         | Trust Center Link Key                         |
+--------------+-----------------------------------------------+
| ZCL          | Zigbee Cluster Library                        |
+--------------+-----------------------------------------------+
| ZDO          | Zigbee Device Object                          |
+--------------+-----------------------------------------------+
| ZC           | Zigbee Coordinator                            |
+--------------+-----------------------------------------------+
| ZR           | Zigbee Router                                 |
+--------------+-----------------------------------------------+
| ZED          | Zigbee End Device                             |
+--------------+-----------------------------------------------+

Reference Documents
-------------------

1. Zigbee document 05-3474-22 Zigbee PRO 2023 (R23) Specification

2. Zigbee document 07-5123-08 Zigbee Cluster Library 8 Specification

3. Zigbee document 13-0402-13 Zigbee Base Device Behavior

4. Zigbee document 14-0563-16 Zigbee Green Power specification

All documentation can be located on the `Connectivity Standards Alliance`_ website.

Zigbee
======

A Zigbee network is a multi-hop network of mains-powered or battery-powered 
devices. This means that successful communication between two devices may 
require intermediate devices to relay messages. Due to the cooperative nature of 
the network, each device is required to perform specific networking functions 
and configure certain parameters to specific values. The role of a device is 
determined by the set of networking functions it performs and is called the 
**logical device type**. The set of parameters that need to be configured to
specific values, along with those values, is called the **stack profile**.

.. _z-stack-overview-logical-device-types:

Logical Device Types
--------------------

The three logical device types in a Zigbee network are
*Coordinator*, *Router*, and *End Device*. A Zigbee network consists
of a device with network formation capabilities (such as Coordinator or Router)
and multiple Router and End Device nodes. Note that the device type does
not in any way restrict the type of application that may run on the
particular device.

.. _fig-typical-zigbee-nwk:
.. figure:: resources/figure1.png
    :align: center

    Example of typical Zigbee network

:ref:`fig-typical-zigbee-nwk` shows a typical Zigbee network with the Zigbee
*Coordinator* (black), the *Routers* (red), and the *End Devices* (white).

An application can be defined as any of these three logical devices depending
on the configuration flags enabled in the project.

+------------------------+-----------------------------------------------+
| **Logical Device**     | **Compilation flags needed**                  |
+========================+===============================================+
| *Coordinator*          | :code:`ZB_COORDINATOR_ROLE`                   |
+------------------------+-----------------------------------------------+
| *Router*               | :code:`ZB_ROUTER_ROLE`                        |
+------------------------+-----------------------------------------------+
| *End Device*           | :code:`ZB_ED_ROLE`                            |
+------------------------+-----------------------------------------------+

.. _z-stack-overview-logical-device-coordinator:

Coordinator
~~~~~~~~~~~

A coordinator is a device with network formation capabilities, but
without network joining capabilities. This means the device can only create its
own network, but not join existing networks. To create a network, the
coordinator node scans the RF environment for existing networks, chooses
a channel and a network identifier (also called PAN ID) and then starts
the network. In Zigbee 3.0 this device creates a Centralized security network
and is mandated to behave as the Trust Center of this network, which
means that this device is responsible for managing security of the
network and is the only device capable of distributing keys and
allowing devices to join the network it has created.

The coordinator node can also be used, optionally, to assist in setting
up application-level bindings in the network.

The role of the coordinator is mainly related to starting the network
and managing the keys. Besides that, it behaves like a router device.
Note that the Coordinator must handle the network procedures
related to devices joining or leaving the network,
so it cannot be absent of its own network.
Further details on security schema are available in :ref:`z-stack-overview-security`.

.. _z-stack-overview-logical-device-router:

Router
~~~~~~

A router performs functions for allowing other devices to join the
network, for multi-hop routing,
and for assisting its child end devices with communication.
In Zigbee 3.0 this device has been granted with formation
capabilities that allow it to create a Distributed security network.
This formation capability allows the router device to create a network
that does not have a security manager. This means that once the network
has been created, the router which created it does not have any special
role in this network. More details are available in :ref:`z-stack-overview-security`.

In general, Routers are expected to be active all the time and thus have
to be mains-powered.

.. _z-stack-overview-logical-device-end-device:

End Device
~~~~~~~~~~

An end device has no specific responsibility for maintaining the network
infrastructure, so it can sleep and wake up as it chooses. This device can
be a battery-powered node. Generally, the memory requirements (especially 
RAM requirements) are lower for an end device.

  .. note::
    In |STACK| all sample application projects are provided with the needed
    pre-include files to build each device type according to the project.

.. _z-stack-layers:

Stack Layers
------------

The following is a brief description of the various |STACK| layers and their 
purpose towards Zigbee functionality.  Note that Zigbee is built on top of 
the IEEE 802.15.4 2006 radio specification.

-  IEEE 802.15.4 PHY: The radio's physical and electrical characteristics

-  IEEE 802.15.4 MAC: Responsible for sending and receiving RF Frames

-  Zigbee-PRO NWK: Handles packets within the confines of a Zigbee network

-  Zigbee-PRO APS: Determines now packets are interpreted by the Zigbee application

-  Zigbee Devices: Commonly referred to as ZDO, this defines how the local device 
   operates within a Zigbee network

-  Base Device Behavior: Standard for commissioning a device in Zigbee network 

-  Manufacturers Application: Including the Zigbee Cluster Library (ZCL), this 
   contains the attributes and clusters which define the Zigbee device's purpose, 
   behavior, and usage within the network.

.. _fig-zigbee-software-architecture:
.. figure:: resources/zigbee-software-architecture.png
    :align: center

    Zigbee Software Architecture

The Zigbee PRO 2023 Compliant Platform layers are pre-built for |DEVICEAND| 
|STACK| devices and require no modification.  Zigbee 3.0 Base Device & Clusters 
layers can be further configured and determined by the developer.

.. _z-stack-overview-stack-profile:

Stack Profile
-------------

The set of stack parameters that need to be configured to specific
values, along with the above device type values, is called a **stack
profile**. The parameters that comprise the stack profile are defined
by the Connectivity Standards Alliance.

All devices in a network must conform to the same stack profile (i.e.,
all devices must have the stack profile parameters configured to the
same values).

If application developers choose to change the settings for any of these
parameters, they can do so with the caveat that those devices will no
longer be able to interoperate with devices from other vendors that
choose to follow the Zigbee specified stack profile. Thus, developers of
“closed networks” may choose to change the settings of the stack profile
variables. These stack profiles are called “network-specific” stack
profiles.

The stack profile identifier that a device conforms to is present in the
beacon transmitted by that device. This enables a device to determine
the stack profile of a network before joining to it. The
“network-specific” stack profile has an ID of 0, the legacy Zigbee
stack profile has ID of 1, and the Zigbee PRO stack profile (which is used
for Zigbee 3.0) has ID of 2. The stack profile is configured by the 
:code:`ZB_STACK_PROFILE` parameter in the :code:`zb_config.h` file. 
The stack profile ID of 3 is reserved for Green Power devices, and it 
appears in the respective frames.

.. _z-stack-overview-addressing:

Addressing
==========

.. _z-stack-overview-address-types:

Address Types
-------------

Zigbee devices have two types of addresses. A 64-bit *IEEE address*
(also called *MAC address* or *Extended address*) and a 16-bit *network
address* (also called *logical address* or *short address*).

The 64-bit address is a globally unique address and is assigned to the
device for its lifetime. It is usually set by the manufacturer or during
installation. These addresses are maintained and allocated by the IEEE.
More information on how to acquire a block of these addresses is
available at `IEEE Registration Authority <https://standards.ieee.org/products-services/regauth/index.html>`_.

The 16-bit address is assigned to a device when it joins a network.
Within that network, it is unique and used for identifying devices and sending data.

.. _z-stack-overview-network-address-assignment:

Network Address Assignment
--------------------------

Stochastic Addressing
~~~~~~~~~~~~~~~~~~~~~

Zigbee PRO uses a stochastic (random) addressing scheme for assigning
the network addresses. This addressing scheme randomly assigns short
addresses to new devices, and then uses the rest of the devices in the
network to ensure there are no duplicate addresses. When a device
joins, it receives its randomly generated address from its parent. The
new network node then generates a “Device Announce” frame (which contains its
new short address and its extended address) to the rest of the network.
If there is another device with the same short address, a router node
in the network will send out a broadcast “Network Status – Address
Conflict” to the entire network and all devices with the conflicting
short address will change its short address. When the conflicted devices
change their address, they issue their own “Device Announce” to check
their new address for conflicts within the network.

End devices do not participate in the “Address Conflict”. Their parents
do that for them. If an “Address Conflict” occurs for an end device, its
parent will issue the end device a “Rejoin Response” message to change
the end device’s short address and the end device issues a “Device
Announce” to check their new address for conflicts within the network.

When a “Device Announce” is received, the association and binding tables
are updated with the new short address, but routing table information is not
updated (new routes must be established). If a parent determines that
the “Device Announce” pertains to one of its end device children, but it
didn’t come directly from the child, the parent will assume that the
child moved to another parent.

.. _z-stack-overview-addressing-in-z-stack:

Addressing in |STACK|
---------------------

In order to send data to a device on the Zigbee network, the application must 
determine a destination address.  In addition to the address itself, the address 
mode parameter also needs to be specified. The destination address mode can take 
one of the following values (defined in :code:`zboss_api_aps.h`):

.. code-block:: c

    /**
    * @name APS addressing mode constants
    * @anchor aps_addr_mode
    */
    /** @{ */
    #define ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT  0x00U /*!< DstAddress and DstEndpoint not present  */
    #define ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT  0x01U /*!< 16-bit group address for DstAddress; DstEndpoint not present */
    #define ZB_APS_ADDR_MODE_16_ENDP_PRESENT            0x02U /*!< 16-bit address for DstAddress and DstEndpoint present */
    #define ZB_APS_ADDR_MODE_64_ENDP_PRESENT            0x03U /*!< 64-bit extended address for DstAddress and DstEndpoint present  */
    #define ZB_APS_ADDR_MODE_BIND_TBL_ID                0x04U /*!< "destination endpoint" is interpreted as an index in the binding table,
                                                                all other destination address information is ignored */

The address mode parameter is necessary because, in Zigbee, packets can
be unicast, multicast, or broadcast. A unicast packet is sent to a single
device, a multicast packet is destined to a group of devices and a
broadcast packet is generally sent to all devices in the network. An indirect 
packet is used when the application does not explicitly know the destination of 
the packet. This is explained in more detail below.

Unicast
~~~~~~~

This is the normal addressing mode and is used to send a packet to a
single device whose network address is known. The address mde is set to
:code:`ZB_APS_ADDR_MODE_16_ENDP_PRESENT` and the destination network address is 
carried in the packet.

Indirect
~~~~~~~~

This is when the application is not aware of the final destination of
the packet. The mode is set to :code:`ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT` 
and the destination address is not specified. Instead, the destination is looked 
up from a *binding table* that resides in the stack of the sending device. This
feature is called Source binding (see :ref:`z-stack-overview-binding`).

When the packet is sent down to the stack, the destination address and
end point is looked up from the binding table and used. The packet is
then treated as a regular unicast packet. If more than one destination
device is found in the binding table, a copy of the packet is sent to
each of them. If no binding entry is found, the packet will not be sent.

Broadcast
~~~~~~~~~

This address mode is used when the application wants to send a packet to
all devices in the network. The address mode is set to 
:code:`ZB_APS_ADDR_MODE_16_ENDP_PRESENT` and the destination address can be set 
to one of the following broadcastaddresses:

0xFFFF – the message will be sent to all devices in the network (includes 
sleeping devices). For sleeping devices, the message is held at its parent until 
the sleeping device polls for it or the message is timed out 
(:code:`NWK_INDIRECT_MSG_TIMEOUT` in
:code:`ti_zstack_config.h`, as generated from the project's .syscfg file 
*RF STACKS* |rarr| *Z-Stack* |rarr| *Advanced* |rarr| *Routing*).

0xFFFD – the message will be sent to all devices that have the receiver on when 
idle (RXONWHENIDLE), that is, all non-sleepy devices.

0xFFFC – the message is sent to all routers (including the coordinator).

Group Addressing
~~~~~~~~~~~~~~~~

This address mode is used when the application wants to send a packet to
a group of devices. The address mode is set to :code:`ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT`
and the address parameter must be set set with the group identifier.

Note that groups can also be used in conjunction with indirect
addressing. The destination address found in the binding table can be
either a unicast or a group address. Also note that broadcast addressing
is simply a special case of group addressing where the groups are set up
ahead of time and defined by Connectivity Standards Alliance.

Important Device Addresses
--------------------------

An application may want to know the address of a device (local). 
Use the following functions to get the addresses.

-  :code:`MAC_PIB().mac_short_address` – Retrieve the short address.

-  :code:`MAC_PIB().mac_extended_address` – Retrieve the IEEE address.

.. _z-stack-overview-binding:

Binding
=======

Binding is a mechanism to control the flow of messages from one
application to another application (or multiple applications). The
binding mechanism is implemented in all devices and is called source
binding.

Binding allows an application to send a packet without knowing the
destination address, the APS layer determines the destination address from its 
binding table, and then forwards the message to the destination application (or 
multiple applications) or group.

.. _z-stack-overview-building-binding-table:

Building a Binding Table
------------------------

There are 3 ways to build a binding table:

-  Zigbee Device Object Bind Request – a commissioning tool can tell the
   device to make a binding record.

-  Zigbee Device Object End Device Bind Request – 2 devices can tell the
   coordinator that they would like to setup a binding table record. The
   coordinator will make the match up and create the binding table
   entries in the 2 devices.

-  Finding and Binding commissioning process for initiator devices.

Zigbee Device Object Bind Request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Any device or application can send a ZDO message to another device (over
the air) to build a binding record for that other device in the network.
This is called Assisted Binding and it will create a binding entry for
the sending device.

The Commissioning Application
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

An application can create a bind between two remote devices by calling 
:code:`zb_zdo_bind_req()`for which are needed the addresses, endpoints, and the
cluster ID wanted in the binding record. The first parameter (target dstAddr) 
is the short address of the binding’s source address (where the binding record 
will be stored) . The remaining parameters are of the remote application device
that the bind will use to send frames. Calling :code:`zb_zdo_unbind_req()` 
can be used, with the same parameters, to remove the binding record.

The target device will send back a Zigbee Device Object Bind or Unbind
Response message. The ZDO code on the coordinator will parse this and
notify the application with either the ZDP transaction sequence number or 
0xFF if operation cannot be performed now (nor enough memory, resources, etc.)

Finding and Binding
~~~~~~~~~~~~~~~~~~~

Base Device Behavior has defined a commissioning method called Finding
and Binding, which is a process that relies on the usage of the Identify
cluster and ZDO messages to allow the commissioned device to find
devices with matching application clusters. This mechanism is usually
triggered by the user to specify which devices need to “Find and Bind”
each other so that these pairs of devices can communicate more effectively.
Refer to section :ref:`z-stack-overview-finding-binding` for further details on 
this commissioning method.

.. _z-stack-overview-routing-overview:

Routing
=======

Overview
--------

A mesh network is described as a network in which the routing of
messages is performed as a decentralized, cooperative process involving
many peer devices routing on each others’ behalf.

The routing is completely hidden from the application layer.
The application simply sends data destined to any device down to the stack
which is then responsible for finding a route. In other words, the application
is unaware of the fact that it is operating in a multi-hop network.

Routing also enables the “self healing” nature of Zigbee networks. If a
particular wireless link is down, the routing functions will eventually
find a new route that avoids that particular broken link. This greatly
enhances the reliability of the wireless network and is one of the key
features of Zigbee.

Many-to-One routing is a special routing scheme that handles the
scenario where centralized traffic is involved. It is part of the Zigbee
PRO feature set to help minimize traffic particularly when all the
devices in the network are sending packets to a gateway or data
concentrator. Many-to-One route discovery is described in detail in
section :ref:`z-stack-overview-many-to-one-routing-protocol`.

.. _z-stack-overview-routing-protocol:

Routing Protocol
----------------

Zigbee uses a routing protocol that is based on the AODV (Ad-hoc
On-demand Distance Vector) routing protocol for ad-hoc networks.
Simplified for use in sensor networks, the Zigbee routing protocol
facilitates an environment capable of supporting mobile nodes, link
failures and packet losses.

Neighbor routers are routers that are within radio range of each other.
Each router keeps track of their neighbors in a “neighbor table”, and
the “neighbor table” is updated when the router receives any message
from a neighbor router (unicast, broadcast, or beacon).

When a router receives a unicast packet, from its application or from
another device, the NWK layer forwards it according to the following
procedure. If the destination is one of the neighbors of the router
(including its child devices) the packet will be transmitted directly to
the destination device. Otherwise, the router will check its routing
table for an entry corresponding to the routing destination of the
packet. If there is an active routing table entry for the destination
address, the packet will be relayed to the next hop address stored in
the routing entry. If a single transmission attempt fails, the NWK layer
will repeat the process of transmitting the packet and waiting for the
acknowledgement, up to a maximum of -nwk data retry times.
If an active entry cannot be found in the routing table
or using an entry failed after the maximum number of retries, a route
discovery is initiated and the packet is buffered until that process is
completed.

Zigbee End Devices do not perform any routing functions. An end device
wishing to send a packet to any device simply forwards it to its parent
device which will perform the routing on its behalf. Similarly, when any
device wishes to send a packet to an end device and initiate route
discovery, the parent of the end device responds on its behalf.

Also in |STACK|, the routing implementation has optimized the routing
table storage. In general, a routing table entry is needed for each
destination device. But by combining all the entries for end devices of
a particular parent with the entry for that parent device, storage is
optimized without loss of any functionality.

Zigbee routers, including the coordinator, perform the following routing
functions:
-  Route discovery and selection
-  Route maintenance
-  Route expiry
These are explained in more detail below.

Route Discovery and Selection
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Route discovery is the procedure whereby network devices cooperate to
find and establish routes through the network. A route discovery can be
initiated by any router device and is always performed in regard to a
particular destination device. The route discovery mechanism searches
all possible routes between the source and destination devices and tries
to select the best possible route.

Route selection is performed by choosing the route with the least
possible cost. Each node constantly keeps track of "link costs" to all
of its neighbors. The link cost is typically a function of the strength
of the received signal. By adding up the link costs for all the links
along a route, a “route cost” is derived for the whole route. The
routing algorithm tries to choose the route with the least “route cost”.

Routes are discovered by using request/response packets. A source device
requests a route for a destination address by broadcasting a Route
Request (RREQ) packet to its neighbors. When a node receives an RREQ
packet it in turn rebroadcasts the RREQ packet. But before doing that,
it updates the cost field in the RREQ packet by adding the link cost for
the latest link and makes an entry in its :ref:`z-stack-overview-route-discovery-table`.

This way, the RREQ packet carries the sum of the link costs along all
the links that it traverses. This process repeats until the RREQ reaches
the destination device. Many copies of the RREQ will reach the
destination device traveling via different possible routes. Each of
these RREQ packets will contain the total route cost along the route
that it traveled. The destination device selects the best RREQ packet
and sends back a Route Reply (RREP) back to the source.

The RREP is unicast along the reverse routes of the intermediate nodes
until it reaches the original requesting node. As the RREP packet
travels back to the source, the intermediate nodes update their routing
tables to indicate the route to the destination. The Route Discovery
Table, at each intermediate node, is used to determine the next hop of
the RREP traveling back to the source of the RREQ and to make the entry
in to the Routing Table.

Once a route is created, data packets can be sent. When a node loses
connectivity to its next hop (it doesn’t receive a MAC ACK when sending
data packets), the node invalidates its route by sending an RERR to all
nodes that potentially received its RREP and marks the link as bad in
its Neighbor Table. Upon receiving a RREQ, RREP, or RERR, the nodes
update their routing tables.

Route Maintenance
~~~~~~~~~~~~~~~~~

Mesh networks provide route maintenance and self healing. Intermediate
nodes keep track of transmission failures along a link. If a link
(between neighbors) is determined as bad, the upstream node will
initiate route repair for all routes that use that link. This is done by
initiating a rediscovery of the route the next time a data packet
arrives for that route. If the route rediscovery cannot be initiated, or
it fails for some reason, a route error (RERR) packet is sent back to
source of the data packet, which is then responsible for initiating the
new route discovery. Either way the route gets re-established
automatically.

Route Expiry
~~~~~~~~~~~~

The routing table maintains entries for established routes. If no data
packets are sent along a route for a period of time, the route will be
marked as expired. Expired routes are not deleted until space is needed.
Thus routes are not deleted until it is absolutely necessary. 

.. _z-stack-overview-routing-table-storage:

Table Storage
-------------

The routing functions require the routers to maintain some tables.

Routing Table
~~~~~~~~~~~~~

Each Zigbee router, including the Zigbee coordinator, contains a routing
table in which the device stores information required to participate in
the routing of packets. Each routing table entry contains the
destination address, the next hop node, and the link status. All packets
sent to the destination address are routed through the next hop node.
Also entries in the routing table can expire in order to reclaim table
space from entries that are no longer in use.

Routing table capacity indicates that a device routing table has a free
routing table entry or it already has a routing table entry
corresponding to the destination address. The routing table size is
configured by :code:`ZB_CONFIG_NWK_ROUTING_TABLE_SIZE` in the
:code:`zb_mem_config_common.h` file. See the section on Route Maintenance for
route expiration details.

.. _z-stack-overview-route-discovery-table:

Route Discovery Table
~~~~~~~~~~~~~~~~~~~~~

Router devices involved in route discovery, maintain a route discovery
table. This table is used to store temporary information while a route
discovery is in progress. These entries only last for the duration of
the route discovery operation. Once an entry expires it can be used for
another route discovery operation. Thus this value determines the
maximum number of route discoveries that can be simultaneously performed
in the network. 

.. _z-stack-overview-many-to-one-routing-protocol:

Many-to-One Routing Protocol
----------------------------

The following explains Many-to-One and source routing procedure for
users’ better understanding of Zigbee routing protocol. In reality, all
routings are taken care in the network layer and transparent to the
application. Issuing Many-to-One route discovery and route maintenance
are application decisions.

Many-to-One Routing Overview
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Many-to-One routing is adopted in Zigbee PRO to help minimize traffic
particularly when centralized nodes are involved. It is common for low
power wireless networks to have a device acting as a gateway or data
concentrator. All nodes in the networks shall maintain at least one
valid route to the central node. To achieve this, all nodes have to
initiate route discovery for the concentrator, relying on the existing
Zigbee AODV based routing solution. The route request broadcasts will
add up and produce huge network traffic overhead. To better optimize the
routing solution, Many-to-One routing is adopted to allow a data
concentrator to establish routes from all nodes in the network with one
single route discovery and minimize the route discovery broadcast storm.

Source routing is part of the Many-to-One routing that provides an
efficient way for concentrator to send response or acknowledgement back
to the destination. The concentrator places the complete route
information from the concentrator to the destination into the data frame
which needs to be transmitted. It minimizes the routing table size and
route discovery traffic in the network.

Many-to-One Route Discovery
~~~~~~~~~~~~~~~~~~~~~~~~~~~

The following figure shows an example of the Many-to-One route discovery
procedure. To initiate Many-to-One route discovery, the concentrator
broadcast a Many-to-One route request to the entire network. Upon
receipt of the route request, every device adds a route table entry for
the concentrator and stores the one hop neighbor that relays the request
as the next hop address. No route reply will be generated.

.. figure:: resources/figure2.png
    :align: center

    Many-to-One route discovery illustration

Many-to-One route request command is similar to unicast route request
command with same command ID and payload frame format. The option field
in route request is Many-to-One and the destination address is 0xFFFC.

Route Record Command
~~~~~~~~~~~~~~~~~~~~

The above Many-to-One route discovery procedure establishes routes from
all devices to the concentrator. The reverse routing (from concentrator
to other devices) is done by route record command (source routing
scheme). The procedure is provided in the :ref:`fig-figure3`. *R1*
sends data packet DATA to the concentrator using the previously
established Many-to-One route and expects an acknowledgement back. To
provide a route for the concentrator to send the ACK back, *R1* sends
route record command along with the data packet which records the
routing path the data packet goes through and offers the concentrator a
reverse path to send the ACK back.

.. _fig-figure3:
.. figure:: resources/figure3.png
    :align: center

    Route record command (source routing) illustration

Upon receipt of the route record command, devices on the relay path will
append their own network addresses to the relay list in the route record
command payload. By the time the route record command reaches the
concentrator, it includes the complete routing path through which the
data packet is relayed to the concentrator. Whenever the concentrator sends
an APS ACK to *R1* in response to a data frame (not due to a route record 
command itself), it shall include the source route (relay list) in the
network layer header of the packet. All devices receiving the packet
shall relay the packet to the next hop device according to the source
route.

A concentrator with no memory constraints can store all route
record entries it receives and use them to send packets to the source
devices in the future. Therefore, devices only need to send a route record
command once. However, for a concentrator without source route caching
capability, devices always need to send route record commands along with
data packets. The concentrator will store the source route temporarily
in the memory and then discard it after usage.

In brief, Many-to-One routing is an efficient enhancement to the regular
Zigbee unicast routing when most devices in the network are funneling
traffic to a single device. As part of the Many-to-One routing, source
routing is only utilized under certain circumstances. First, it is used
when the concentrator is responding to a request initiated by the source
device. Second, the concentrator should store the source route
information for all devices if it has sufficient memory. If not,
whenever devices issue requests to the concentrator, they should also
send a route record along with it.

Many-to-One Route Maintenance
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If a link failure is encountered while a device is forwarding a
Many-to-One routed frame (notice that a Many-to-One routed frame itself
has no difference from a regular unicast data packet, however, the
routing table entry has a field to specify that the destination is a
concentrator), the device will generate a network status command with
code “Many-to-One route failure”. The network status command will be
relayed to the concentrator through a random neighbor and hopefully that
neighbor still has a valid route to the concentrator. When the
concentrator receives the route failure, the application will decide
whether or not to re-issue a Many-to-One route request.

.. _z-stack-overview-routing-off-network-association-cleanup:

Router Off-Network Association Cleanup
--------------------------------------

In case a Zigbee Router gets off network for a long period of time, its
children will try to join an alternative parent. When the router is back
online, the children will still appear in its child table, preventing
proper routing of egress traffic to them.

.. _z-stack-overview-portable-devices:

Portable Devices
================

An End Device detects that a parent isn’t responding either through
polling (MAC data requests) failures and/or through data message
failures.

When the network layer detects that its parent isn’t responding, it will trigger
the process of scanning the channel in which this device was commissioned,
in order to search another suitable parent device. It is recommended
that as soon as an end device loses its parent, it should try to
recover. If recovery fails, the device should try once again after a
short delay, and if it still fails, it should retry periodically with a
larger waiting period. This practice allows for better power usage on
the end device and does not interfere with other networks that may be on
the same channel.

In secure networks, it is assumed that the device already has a key and
a new key isn’t issued to the device.

The end device’s short address is retained when it moves from parent to
parent; routes to such end devices are re-established automatically.

.. _z-stack-overview-end-toend-ack:

End-to-End Acknowledgements
===========================

For non-broadcast messages, there are basically 2 types of message
retries: end-to-end acknowledgement (APS ACK) and single-hop
acknowledgement (MAC ACK). MAC ACKs are always on by default and are
usually sufficient to guarantee a high degree of reliability in the
network. To provide additional reliability, as well as to enable the sending device 
to get confirmation that a packet has been delivered to its destination, 
APS acknowledgements may be used.

APS acknowledgement is done at the APS layer and is an acknowledgement
system from the destination device to the source device. The sending
device will hold the message until the destination device sends an APS
ACK message indicating that it received the message. 

.. _z-stack-overview-miscellaneous:

Miscellaneous
=============

.. _z-stack-overview-configuring-channel:

Configuring Channel
-------------------

Every Zigbee 3.0 device has a primary channel mask configuration
(:code:`DEFAULT_CHANLIST`). For devices with formation capabilities that were 
instructed to create a network, these
channels masks are used when scanning for a channel with the least
number of networks to create the new network on. For devices with joining
capabilities that were instructed to join a network, these channel masks
are used when scanning for existing networks to join. The device will
try first with all the channels defined in the primary channel mask.
If the process is not successful
(the network was not created or no network to join was found),
then the secondary channel mask is used.
These two channel masks can be configured by the application as needed. A
value of 0 in one of these masks will disable the respective channel
scanning phase (primary or secondary).

The default primary channel mask is defined as :code:`DEFAULT_CHANLIST`, in 
:code:`ti_zigbee_config.h`, which is generated from the project's .syscfg 
(*RF STACKS* |rarr| *Zigbee* |rarr| *Radio*). The 
:ref:`z-stack-overview-commissioning` section provides more details on the 
commissioning methods.

.. _z-stack-overview-configuring-pan-id-and-network-joining:

Configuring the PAN ID and Network to Join
------------------------------------------

The 16-bit PANID of a network is determined by the :code:`ZDAPP_CONFIG_PAN_ID` 
parameter in :code:`ti_zstack_config.h`, as generated by the .syscfg file of the 
project (see :ref:`sysconfig-zigbee-configuration`).

If set to a value between 0x0000 and 0xFFFE (inclusive),
a coordinator or a network-forming router will use this value as the PAN ID of 
the network when instructed to create a network, and a joining router or end 
device will only join a network that has a PAN ID which matches the value of 
this parameter.

If set to 0xFFFF, 
a newly formed network will have a random PAN ID, and 
a joining device will be able to join any network regardless of its PAN ID.

This is an optional configuration item to control which network a Zigbee
Router or End Device will join. It can also be used to pre-set the PAN
ID of a new network that a coordinator or router will create.

The network discovery process is managed by the Network Steering
commissioning process, which is explained in :ref:`z-stack-overview-nwk-steering-not-on-nwk`.
It allows filtering of the discovered networks. 
After the scan (using either primary or secondary channel masks) is complete, 
the application receives a list of network descriptors of the networks 
found during the scan.

.. _z-stack-overview-maximum-payload-size:

Maximum Payload Size
--------------------

The maximum payload size for an application is based on several factors.
The MAC layer provides a constant payload length of 125 bytes. The NWK layer requires a
fixed header size, one size with security and one without security. The
APS layer has a required, but variable, header size based on a variety
of settings, including the Zigbee Protocol Version, APS frame control
settings, etc. Ultimately, the user does not have to calculate the
maximum payload size using the aforementioned factors. 

.. _z-stack-overview-leave-nwk:

Leave Network
-------------

The ZDO Management implements the function :code:`zb_zdo_mgmt_leave_req()`,
which provides access to the “NLME-LEAVE.request” primitive.
“NLME-LEAVE.request” allows a device to remove itself or a remote
device from the network.  When a device removes a child device, it also removes 
the device from the local “association table”. The NWK address will only be 
reused in the case where a child device is a Zigbee End Device. In the case of
a child Zigbee Router, the NWK address will not be reused.

If the parent of a child device leaves the network, the child will stay
on the network.

Since R21 of the Zigbee PRO specification, processing of “NWK Leave
Request” has been configurable for Routers. Processing
of these commands, depending on the logical device type, has also changed:
Coordinators do not process leave commands, Router devices process leave
commands from *any* device in the network (if allowed as mentioned
above), and end devices only process leave commands from their parent
device.

In the Base Device Behavior Specification, it is also stated that if any
device receives a valid leave request with rejoin set to :code:`FALSE` (meaning
that this device shall not rejoin the network), then that device is 
forced to perform a Factory New reset. In this case, |STACK| clears all 
the Zigbee persistent data, while it is up to the application to clear 
the relevant application data from NV.

.. _z-stack-overview-descriptors:

Descriptors
-----------

All devices in a Zigbee network have descriptors that describe the type
of device and its applications. This information is available to be
discovered by other devices in the network.

.. _sec-asynchronous-links:

Asynchronous Links
------------------

An asynchronous link occurs when a node can receive packets from another
node but it can’t send packets to that node. Whenever this happens, this
link is not a good link to route packets.

In Zigbee PRO, this problem is overcome by the use of the Network Link
Status message. Every router in a Zigbee PRO network sends a periodic
Link Status message. This message is a one hop broadcast message that
contains the sending device’s neighbor list. The idea is this – if you
receive your neighbor’s Link Status and you are either missing from the
neighbor list or your receive cost is too low (in the list), you can
assume that the link between you and this neighbor is an asynchronous
link and you should not use it for routing.

To change the time between Link Status messages you can change the
compile flag :code:`ZB_NWK_LINK_STATUS_PERIOD`. Remember that only PRO routers 
send the link status message and that every router in the network must have the 
same Link Status time period.

Another parameter that affects the Link Status message is
:code:`ZB_NWK_ROUTER_AGE_LIMIT` (default of 3). This
represents the number of Link Status periods that a router can remain in
a device’s neighbor list, without receiving a Link Status from that
device, before it becomes aged out of the list. If a device doesn’t received a
Link Status message from a neighbor within (:code:`ZB_NWK_ROUTER_AGE_LIMIT` *
:code:`ZB_NWK_LINK_STATUS_PERIOD`), the device will age the neighbor out and 
assume that this neighbor is missing or that it’s an asynchronous link and not 
use it.

Multicast Messages
------------------

This feature is a Zigbee PRO only feature.  This feature is similar to sending 
to an APS Group, but at the network layer.

A multicast message is sent from a device to a group as a MAC broadcast
message, which includes a non-member radius field. The receiving device will 
determine if it is part of that group. If it isn’t part of the group, then it 
will decrement the non-member radius and rebroadcast. If it is part of the group, 
then it will first set the non-member radius equal to the group radius, and then 
rebroadcast the message. If the non-member radius is decremented to 0, the 
message isn’t rebroadcast.

The difference between multicast and APS group messages can only be seen
in very large networks, where the non-member radius will limit the number
of hops away from the group.

Fragmentation
-------------

Message Fragmentation is a process where a large message – too large to
send in one APS packet – is broken down and transmitted as smaller
fragments. The fragments of the larger message are then reassembled by
the receiving device.

When APS Fragmentation is turned on, sending a data request with a
payload larger than a normal data request payload will automatically
trigger fragmentation.

.. _extended-pan-id:

Extended PAN IDs
----------------

By default, the 64-bit Extended PAN ID (EPID) is set to the device's own IEEE address.
If a pre-determined EPID is required, the developer changes this in the project's .syscfg file.

Rejoining with Pre-Commissioned Network Parameters
--------------------------------------------------

In previous Zigbee stacks, it was possible for a rejoining device to use
a pre-configured network address. As of today, the Base Device Behavior
specification has not addressed this topic (whether this is allowed or
not). TI encourages the use of the Base Device Behavior commissioning
methods described in :ref:`z-stack-overview-commissioning` for rejoining the network.

.. WIP

    .. _sec-child-management:

    Child Management
    ----------------

    The Child Management feature allows mobility in end devices and saves space
    within parent devices’ association tables.When an end device joins/rejoins, it
    will send an EndDeviceTimeout NWK command, which contains a timeout period. If
    their parent does not receive a keep-alive message from the end device within
    the timeout period, it will remove the end device from its association table and
    send that end device a leave request.

    The parent device will answer the EndDeviceTimeout NWK command with a response
    stating which methods it supports for receiving the keep-alive messages.There
    are two keep-alive methods, MAC polling and timeout message. An end
    device timeout message is preferred for Zigbee 3.0 devices where power
    consumption is important as it does not require the end device to constantly
    send data request frames other than needed by polling data from parent. MAC
    polling is compatible with end devices who implement any Zigbee specification
    prior to Zigbee 3.0 without the need for specific child aging support.

    If a legacy device joins an R21 or later parent device, the parent will assign a
    default timeout to expire this device if this legacy device fails to poll in a
    timely manner. Additionally, if a parent device is polled by an end device which
    is not its child (due to being expired or not being its child at all), then the
    parent device must request this end device to leave the network with rejoin set
    to :code:`TRUE`.Then this device can rejoin the network and find a new parent
    (which could be the same router or another one).

    Configuring Child Management for Parent Device
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    A default end device timeout can be defined in the parent device by modifying
    :code:`NWK_ED_DEVICE_TIMEOUT_DEFAULT`. This timeout will be overwritten by joining
    devices if they state their own timeout using the EndDeviceTimeout command.

    Parent devices must keep track of devices that it should send leave requests to.
    To do this, parent devices must queue leave requests in the MAC layer.
    The number of devices that can be kept track of at the
    same time is defined by :code:`ZB_DEFAULT_MAX_CHILDREN` (in :code:`zb_config_common.h`).

    Configuring Child Management for Child Devices
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    The timeout that the child device will indicate to its parent device
    is defined by :code:`END_DEV_TIMEOUT_VALUE` (see *RF STACKS* |rarr| *Z-Stack* |rarr| 
    *Network* |rarr| *End Device Timeout* (see :ref:`sysconfig-zigbee-configuration`).
    Its suggested value should be at least 3 times greater than the MAC polling time
    (set by :code:`POLL_RATE` in :code:`ti_zstack_config.h`)
    to avoid being expired if there is interference when the end device is polling.  
    The minimum allowable application poll rate is determined by :code:`MINIMUM_APP_POLL_RATE` 
    in :code:`ti_zstack_config.h` but can be changed by calling 
    :code:`zb_set_keepalive_timeout`.

    .. _sec-parent-annce:

    Parent Annce
    ~~~~~~~~~~~~

    The child management functionality includes the usage of Parent Annce ZDO messages.
    A parent broadcasts this message only when forming a network or when reset,
    after 10 seconds plus a random jitter of up to 10 seconds.
    The message contains the 64-bit IEEE addresses of all end devices in the parent’s association table.
    If another parent device receives this message, it will check if any of the reported children
    is also listed in its own association table.
    If there are any matches, then this parent device will respond to the originator of the message
    with a list of all matches. The originator will then remove those children from its association table.
    The usage of this message can be illustrated with the following example:

    1) Parent device ‘A’ has a child device ‘c’.

    2) Parent device ‘A’ is power cycled.

    3) Child device ‘c’ finds parent device ‘B’ and joins it.

    4) When parent device ‘A’ restores its network parameters, it starts a
    timer to send parent annce (of 10 seconds plus random jitter of up to
    10 seconds.)

    5) After the timeout, parent device ‘A’ broadcasts parent annce
    containing IEEE address of child ‘c’.

    6) Parent device ‘B’ finds a match with its children and responds with a
    parent annce response containing the IEEE address of child ‘c’.

    7) Parent device ‘A’ removes child ‘c’ from its table.

    .. _z-stack-overview-security:

    Security
    ========

    Overview
    --------

    Zigbee security is built with the AES block cipher and the CCM mode of
    operation as the underlying security primitive. AES/CCM security
    algorithms were developed by external researchers outside of Zigbee
    Alliance and are also used widely in other communication protocols.

    Zigbee specification defines two types of networks, based on the
    security schema that those networks use: Centralized security network
    and Distributed security network.

    By default, networks are closed for new devices. In both types of
    networks, the network can only be opened for a maximum of 254 seconds at
    a time, after which the network will be closed for joining. Zigbee 3.0
    networks cannot remain open indefinitely.   The default value for Zigbee
    is 180 seconds as determined by :code:`ZB_BDBC_MIN_COMMISSIONING_TIME_S` in
    :code:`zb_config_common.h`.  The duration for which devices
    may attempt to join a network is reflected in the beacon packets sent by
    any existing networks in response to a joining device's beacon requests.

    Zigbee offers the following security features:

    -  Infrastructure security

    -  Network access control

    -  Application data security (only for centralized security networks)

    Configuration
    -------------

    Network layer security is mandatory in Zigbee 3.0 and cannot be disabled.

    The default key for network layer encryption is distributed to each joining
    device over-the-air as they join the network.  This default key is initialized 
    with the macro definition :code:`DEFAULT_KEY` in :code:`ti_zstack_config.h`. 
    The developer specifies :code:`DEFAULT_KEY` in the project's .syscfg file 
    (see :ref:`sysconfig-zigbee-configuration`). If this key is set to 0 upon initialization, 
    then a random key will be generated. In Zigbee 3.0 this key is transmitted over-the-air 
    to joining devices using APS layer encryption.

    Centralized Security Network
    ----------------------------

    This network type is formed by coordinator devices, in which the
    coordinator assumes the role of Trust Center (TC). In this type of network only the TC
    can deliver the network key to joining devices and allow them to be part of the network.
    The coordinator can configure different sets of TC policies
    that allow control of the security level of the network. These policies
    will be presented in :ref:`sec-trust-center-policies`. When a device performs an
    association directly to the TC, the TC will evaluate the TC policies and
    validate if the device is allowed to join the network or not. When a
    device joins through a router device, the parent device notifies the TC
    via an APS Update Device command, and then the joining device will go
    through the same TC policy validations. If a device passes the
    validations, the TC will deliver the network key to the joining device
    through either a direct APS Transport Key command or an APS Tunnel
    Transport Key command, depending on the device's joining topology. If the
    joining device does not pass the TC policy validations, it will be
    kicked out of the network with a network leave command.

    It is also important to note that if the TC is not available (power
    cycled or not in the network), new devices will not be able to join the
    network since no other device is allowed to deliver the network key or
    validate TC policies.

    .. _sec-trust-center-policies:

    Trust Center Policies
    ~~~~~~~~~~~~~~~~~~~~~

    zgAllowRemoteTCPolicyChange
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^

    If :code:`allow_remote_policy_change` of :code:`zb_aps_globals.c` is set to :code:`1` 
    (default), other devices in the network may modify
    the permit joining policy of the Trust Center, which could allow other
    devices to join the network. If set to :code:`0`, remote devices will not be
    able to change the permit joining policy on the coordinator, which will
    cause the TC to not deliver the network key and kick out any devices
    attempting to join the network through an intermediate router which may
    have locally enabled permit join.

    bdbJoinUsesInstallCodeKey
    ^^^^^^^^^^^^^^^^^^^^^^^^^

    If :code:`ZB_JOIN_USES_INSTALL_CODE_KEY` from :code:`zb_aps_globals.h` is 
    set to :code:`TRUE`, then the network key will be delivered only to those joining 
    devices that do have an install code associated. If 
    :code:`ZB_JOIN_USES_INSTALL_CODE_KEY` is set to :code:`FALSE` (default), 
    joining devices may use install codes. The usage of install codes is described
    in :ref:`sec-install-code-usage`.

    .. _sec-bdbTrustCenterRequireKeyExchange:

    bdbTrustCenterRequireKeyExchange
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    If :code:`BDB_DEFAULT_TC_REQUIRE_KEY_EXCHANGE` in :code:`bdb_interface.h` is set 
    to :code:`TRUE`, then all the joining devices are mandated to perform the
    TCLK exchange procedure. Devices that do not perform this procedure will
    be kicked out of the network after :code:`ZB_DEFAULT_BDB_TRUST_CENTER_NODE_JOIN_TIMEOUT` seconds
    (15 by default). If this policy set to :code:`FALSE` (default), joining devices will not
    be required to perform a TCLK update, but they will be allowed to do so.
    The TCLK exchange procedure is described in :ref:`sec-unsecure-join-centralized-network`.

    .. note:: Legacy devices (implementing R20 or before)
        will not be able to perform the TCLK exchange process, so if this policy
        is set to :code:`TRUE`, legacy devices will not be able to join this network.

    Key Updates
    ~~~~~~~~~~~

    The Trust Center can update the common Network key at its discretion. An
    example policy would be to update the Network key at regular periodic
    intervals. Another would be to update the NWK key upon user input (like
    a button-press). The Security subsystem :code:`zboss_api.h` API provides this
    functionality via :code:`zb_secur_nwk_key_switch_procedure()` allows the Trust Center to send x
    a new Network key to the dstAddr on the network. At this point the new Network key is
    stored as an alternate key in the destination device(s).
    Once the Trust Center calls :code:`zb_secur_nwk_key_switch_procedure()` with the 
    dstAddr of the device or devices, all destination devices will use their alternate key.

    Since the R21 revision of the Zigbee specification,
    the network frame counter is mandated to be persistent across factory new resets.
    However, it can be reset to 0 if the network frame counter is larger than half of its max value (0x8000000)
    prior to performing a network key update. Performing the update will then reset the frame counter to 0.

    .. _sec-distributed-security-network:

    Distributed Security Network
    ----------------------------

    This network type can be formed by network-forming router devices. In
    this network topology, all the nodes have the ability to open the
    network for joining and any router device can deliver the network key to
    a joining device. The network key will be encrypted at APS layer with a
    Default Distributed Global key (detailed in :ref:`sec-distributed-global-key`). 
    This network key will
    be delivered via an APS Transport Key Command in which the TC address
    will be set to 0xFFFFFFFFFFFFFFFF, which tells the joining device that it is
    joining a distributed security network.  The feature is enabled through the
    :code:`ZB_DISTRIBUTED_SECURITY_ON` definition.

    It is important to note that after a distributed network is formed, the
    network key cannot be updated because there is no defined method of
    securely distributing a network key in a network with this topology.

    Link Key Types
    --------------

    Each node must support a way to use the following link key types:

    1. The default global Trust Center link key

    2. An install code derived Trust Center link key.

    3. The distributed security global link key

    4. The touchlink preconfigured link key (if touchlink enabled).

    .. _sec-default-global-tclk:

    Default Global Trust Center Link Key
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    All devices share a default global Trust Center Link Key. This is an APS
    layer key and is the first key to be used when joining a network, if no
    other link key is specified. This key is defined by SysConfig and cannot 
    be modified if interoperability with other Zigbee 3.0 devices is desired.

    +-----------------------------------------------+-----+---------------------+
    | Default global Trust Center link key (0:15)   | =   | 0x5a 0x69 0x67 0x42 |
    |                                               |     | 0x65 0x65 0x41 0x6c |
    |                                               |     | 0x6c 0x69 0x61 0x6e |
    |                                               |     | 0x63 0x65 0x30 0x39 |
    +-----------------------------------------------+-----+---------------------+

    .. _sec-install-code-usage:

    Install Code Derived Trust Center Link Key
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    An Install Code is a sequence of 16 bytes followed by 2 bytes of CRC. A
    complete 18 bytes sequence is needed to generate a unique TCLK. The
    usage of install codes defined in Zigbee 3.0 was added to allow a generalized
    out-of-band key delivery method for network commissioning. It works as
    follows:

    1. TC gets the install code and the 64-bit IEEE address of the device
    that will use this install code to join, via any user interface
    (serial, display, switches, etc.). The install code must be
    physically provided with the joining device.

    2. TC validates the CRC of the install code introduced. If this is valid
    then a TCLK entry is added into the TC with the derived key and the
    address of the corresponding device.

    3. The joining device is instructed to use its install code to generate
    the corresponding TCLK.

    4. The network is opened.

    5. The joining device performs association and the Trust Center delivers
    the network key encrypted in APS layer with the install code derived
    key.

    6. After this, the joining device must perform the update of its TCLK as
    BDB specification requires.

    This is accomplished by setting :code:`ZB_JOIN_USES_INSTALL_CODE_KEY`
    and using the :code:`zb_secur_ic_add()` API.  For further details on how to generate 
    the install codes, see the Base Device Behavior Specification. This is supported 
    only by R21 or later revisions, so to allow backwards compatibility the application 
    must have a way to attempt joining networks without the usage of Install Codes.

    .. _sec-distributed-global-key:

    Distributed Security Global Link Key
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    When a device joins a distributed security network (no TC),
    the parent router device sends the network key after encrypting it in the 
    APS layer using the Distributed Global link key, defined in SysConfig. 
    This key cannot be modified if interoperability with other Zigbee 3.0 
    devices is desired.

    +--------------------------------------------+-----+--------------------------+
    | Distributed Trust Center link key (0:15)   | =   | 0xd0 0xd1 0xd2 0xd3 0xd4 |
    |                                            |     | 0xd5 0xd6 0xd7 0xd8 0xd9 |
    |                                            |     | 0xda 0xdb 0xdc 0xdd 0xde |
    |                                            |     | 0xdf                     |
    +--------------------------------------------+-----+--------------------------+

    Touchlink Preconfigured Link Key
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    This key is used for development of a device that will join a network
    using the Touchlink commissioning procedure, defined by
    :code:`ZB_TOUCHLINK_PRECONFIGURED_KEY` of :code:`zb_config_common.h`

    +-------------------------------------------+-----+--------------------------+
    | Touchlink preconfigured link key (0:15)   | =   | 0xc0 0xc1 0xc2 0xc3 0xc4 |
    |                                           |     | 0xc5 0xc6 0xc7 0xc8 0xc9 |
    |                                           |     | 0xca 0xcb 0xcc 0xcd 0xce |
    |                                           |     | 0xcf                     |
    +-------------------------------------------+-----+--------------------------+

    Unsecure Join to a Network
    --------------------------

    Base Device Behavior has defined the procedure in which a device has to 
    commission itself into a network from a factory new state. The procedure 
    specifies how the joining device discovers networks across one set of channels,
    and how it can fall back to discover additional networks in the remaining 
    channels, refer to :ref:`z-stack-overview-nwk-steering-not-on-nwk`.
    Once the device has selected a suitable network, the joining device determines 
    if it has joined a Centralized or Distributed security network.
    These networks use different keys to encrypt the APS Transport command.
    The specific secure procedures to join these types of secure networks
    will be explained in the following subsections.

    .. _sec-unsecure-join-centralized-network:

    Unsecure Join to a Centralized Network
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Once the joining device receives the transport key,
    it will proceed to check the source address of that transport key command.
    In this case the 64-bit IEEE address will be different from all 00’s or FF’s
    since the TC exists in this network. The following steps describe the unsecure 
    joining process to a Centralized network. The joining process into a Zigbee 3.0 
    Centralized network directly to the TC is illustrated in
    :numref:`fig-direct-join-tc`.

    1. Joining device sends association request.

    2. Parent device sends association response.

    3. Trust Center delivers the network key in a Transport key command.
    This transport key command is APS encrypted either with 
    :ref:`sec-default-global-tclk` or an
    :ref:`sec-install-code-usage`.

    4. Joining device is able to get the network key from the encrypted
    Transport Key command and announces itself with a ZDO device announce
    command.

    5. The joining device then queries the ZDO Node Descriptor from the
    Trust Center.

    6. The joining device parses the Node Descriptor to look at the stack
    version revision (this field has been added since the R21 version of Zigbee
    specification).

    a. If the stack version supported by the TC is not present (0x00),
        this means it supports a version from before to R21, so the
        joining process will finish at this step.

    b. If the TC of the joined network is R21 or later, the joining
        device must update its APS Key by sending an APS Request Key command.

    7. The TC will deliver the Unique Trust Center link key with an APS
    Transport Key command.

    8. The joining device will update its key status from *Default* or
    *Provisional* (if an install code was used) to *Unverified*, after
    which the key must be verified. To verify the key, the joining device
    will send an APS Verify Key command to the TC containing the *Unique*
    key hashed (to avoid sending the key in plain text).

    9. The TC hashes the key associated to this device and compares against
    the hashed key received. If they are the same, it will send an APS Confirm
    Key command with status *Success*, after which the TCLK exchange
    procedure is finished for the joining device.

    If any steps between 1 and 4 fail, the joining device will reattempt steps 1 to 4
    up to :code:`BDBC_REC_SAME_NETWORK_RETRY_ATTEMPS` (:code:`bdb_interface.h`) times 
    with the same network. If there are no successes within these attempts, the joining 
    device will retry with the next suitable network in the network descriptor list.
    Similarly, if any steps between 5 and 8 fail, the joining device will reattempt
    those steps up to :code:`ZB_DEFAULT_BDB_TCLINK_KEY_EXCHANGE_ATTEMPTS_MAX`
    (:code:`zb_config_common.h`) times. If there are no successes, then the device will perform a 
    Factory New reset to erase the network parameters and keys obtained at the failing step.
    The application will receive a notification of these, as detailed in :ref:`sec-bdb-notifications`.

    .. _fig-direct-join-tc:
    .. uml::
        :caption: Joining Directly to Trust Center
        :align: center

        @startuml
        "Trust Center" <- "Joining Device": Association Request
        activate "Trust Center"
        "Joining Device" <-- "Trust Center": Association Response
        deactivate "Trust Center"

        "Trust Center" <- "Trust Center": Trust Center use Default TCLK or\nderived key from install code
        "Joining Device" <- "Trust Center": Transport Key
        "Trust Center" <- "Joining Device": Device Announce
        "Trust Center" <- "Joining Device": Node Descriptor Request

        activate "Trust Center"
        "Joining Device" <-- "Trust Center": Node Descriptor Response
        deactivate "Trust Center"
        "Joining Device" <- "Joining Device": Get trust center capabilities and stack revision

        "Trust Center" <- "Joining Device": Request Key
        activate "Trust Center"
        note right: Requesting Key Type: [0x04] Trust Center Key
        "Joining Device" <-- "Trust Center": Transport Key
        deactivate "Trust Center"

        "Trust Center" <- "Joining Device": Verify Key
        activate "Trust Center"
        "Trust Center" <- "Trust Center": Process key hash to verify the APS key
        "Joining Device" <-- "Trust Center": Confirm Key
        deactivate "Trust Center"
        @enduml

    A similar process occurs when the device joins through a parent device
    that is not the TC. The parent device sends APS Update device commands
    to the TC to notify it about the new device. Afterwards, the parent device
    only relays the frames between the joining device and the TC as
    illustrated in :numref:`fig-indirect-join-tc`.

    .. _fig-indirect-join-tc:
    .. uml::
        :caption: Joining When Parent is not the Trust Center
        :align: center

        @startuml
        participant "Trust Center"
        participant "Parent Router"
        participant "Joining Device"

        "Joining Device"->"Parent Router": Association Request
        activate "Parent Router"
        "Parent Router"-->"Joining Device": Association Response
        deactivate "Parent Router"

        "Trust Center"->"Trust Center": Trust Center use Default TCLK or\nderived key from install code
        "Parent Router"->"Trust Center": Update Device
        activate "Trust Center"
        "Trust Center"-->"Parent Router": Tunnel: Transport Key
        deactivate "Trust Center"

        "Parent Router"->"Joining Device": Transport Key
        "Joining Device"-->"Parent Router": Device Announce
        "Parent Router"-->"Trust Center": Device Announce

        "Joining Device"->"Parent Router": Node Descriptor Request
        activate "Parent Router"
        "Parent Router"->"Trust Center": Node Descriptor Request
        activate "Trust Center"
        "Trust Center"-->"Parent Router": Node Descriptor Response
        deactivate "Trust Center"
        "Parent Router"-->"Joining Device": Node Descriptor Response
        deactivate "Parent Router"
        "Joining Device"->"Joining Device": Get trust center capabilities and stack revision

        "Joining Device"->"Parent Router": Request Key
        activate "Parent Router"
        note right: Requesting Key Type: [0x04] Trust Center Key
        "Parent Router"->"Trust Center": Request Key
        activate "Trust Center"
        "Trust Center"-->"Parent Router": Transport Key
        deactivate "Trust Center"
        "Parent Router"-->"Joining Device": Transport Key
        deactivate "Parent Router"

        "Joining Device"->"Parent Router": Verify Key
        activate "Parent Router"
        "Parent Router"->"Trust Center": Verify Key
        activate "Trust Center"
        "Trust Center"->"Trust Center": Process key hash to verify the APS key
        "Trust Center"-->"Parent Router": Confirm Key
        deactivate "Trust Center"
        "Parent Router"-->"Joining Device": Confirm Key
        deactivate "Parent Router"
        @enduml

    Trust Center (TC) Rejoin
    ~~~~~~~~~~~~~~~~~~~~~~~~

    Although secure rejoins (NWK encrypted) are preferred, in some situations a device may no longer have knowledge of the NWK key of its current network.
    In this case, a TC rejoin (unsecure) could be performed.
    The Rejoin Request would be unencrypted. 
    Depending on its policies, the TC may choose to transport the current NWK key (APS encrypted) to the joining device.
    If this device had previously joined, the TC would use the unique TCLK for that joining device.
    Otherwise, the TC may use the well-known global TCLK.

    This feature is tuned with the following functions:

        - :code:`zb_secur_set_ignore_tc_rejoin`: Specifies whether Trust Center Rejoin is ignored
        - :code:`zb_secur_set_tc_rejoin_enabled`: Specifies whether unsecure Trust Center Rejoin is allowed
        - :code:`zb_secur_set_unsecure_tc_rejoin_enabled`: Specifies whether Trust Center Rejoin is allowed, when there is no unique TCLK. On joiner device it could be used to perform TC rejoin with legacy ZC.

    .. _fig-tc-rejoin:
    .. uml::
        :caption: TC Rejoin
        :align: center

        @startuml
        participant "Trust Center"
        participant "Parent Router"
        participant "Joining Device"

        "Joining Device"->"Parent Router": Rejoin Request (no NWK encryption)
        activate "Parent Router"
        "Parent Router"->"Joining Device": Rejoin Response (no NWK encryption)
        deactivate "Parent Router"

        "Parent Router"->"Trust Center": Update Device
        activate "Trust Center"
        "Trust Center"->"Trust Center": Decision to accept TC rejoin
        deactivate "Trust Center"

        "Trust Center"->"Parent Router": Transport Key (APS encrypted)
        note right: Transport Key Type: [0x01] NWK Key
        "Parent Router"->"Joining Device": Transport Key
        @enduml


    Unsecure Join to a Distributed Network
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Once the transport key is received by the joining device, it will
    proceed to check the source address of this transport key command. In
    this case, the 64-bit IEEE address will be all FF’s, indicating that this is
    a distributed network. Also, there are no additional procedures
    to perform updates of keys, since there is no TC that can handle this.
    The joining process into a Zigbee 3.0 Distributed network is illustrated in
    :numref:`fig-join-distributed-nwk`.

    .. _fig-join-distributed-nwk:
    .. uml::
        :caption: Distributed Security Joining
        :align: center

        @startuml
        participant "Parent Router"
        participant "Joining Device"
            "Joining Device"->"Parent Router": Association Request
            "Parent Router"-->"Joining Device": Association Response
            "Parent Router"->"Parent Router": Trust Center use Distributed Key
            "Parent Router"->"Joining Device": Transport Key
            "Joining Device"-->"Parent Router": Device Announce
        @enduml

    The joining device will attempt up to
    :code:`ZB_NWK_REJOIN_POLL_ATTEMPTS` to join this network. If it
    cannot be authenticated (receives the network key), then it will try the
    next network in the network descriptor list.

    Z-Stack Security Considerations
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    .. _sec-tc-joining:

    For Trust Center (TC) Devices
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    Trust center devices have a TCLK manager which stores the APS secure
    information related to a particular joining device (IEEE address, frame
    counters, key, key status). Each TCLK entry is stored in NV, up to a maximum 
    defined by :code:`ZB_CONFIG_N_APS_KEY_PAIR_ARR_MAX_SIZE`. A TCLK entry is 
    created for each joining device that the TC sends the network key to.
    This limits the number of devices in the network to the number of TCLK entries that the TC has.
    A TCLK entry is also used when an Install Code is introduced to the TC for a joining device,
    but the Install Code key is saved in a separate table of NV. When the TCLK 
    exchange is complete for a joining device, the TC frees the corresponding 
    Install Code key entry from NV, but continues using the TCLK entry. However, 
    since the TCLK entries are used to keep track of the APS Key,
    which is not updated from the Global Default Centralized Key by legacy devices 
    (R20 or before), it does not make sense to keep TCLK entries for legacy devices.
    For this reason the TC will erase the TCLK entry.
    Then it will either kick that device out of the network or leave it in the network (depending on 
    the configuration of :code:`ZB_LITE_NO_TRUST_CENTER_REQUIRE_KEY_EXCHANGE`).
    This optimization allows a Zigbee 3.0 TC device to form a network of up to
    :code:`ZB_CONFIG_OVERALL_NETWORK_SIZE` Zigbee 3.0 devices and as many legacy devices as possible
    (limited by other parameters or topology configurations).  This setting is configured
    from the project's .syscfg file *RF STACKS* |rarr| *Z-Stack* |rarr| *Network*.

    For Joining Devices
    ^^^^^^^^^^^^^^^^^^^

    When a factory new device receives an APS Transport Key command, it must decrypt the contents 
    of the command to determine which type of network it’s joining (centralized or distributed). 
    The device first assumes a centralized network, thus using its Install Code (if loaded through 
    BDB API) or the Global Default Centralized Key to decrypt. If the decryption fails, Z-Stack 
    will automatically try decrypting with the Global Default Distributed Key.

    The secure procedures to join Centralized or Distributed networks are
    already implemented by the BDB layer.

    Joining devices must consider that the APS TCLK exchange will involve
    NV reads/writes of the APS security material by the TC,
    so if multiple devices are meant to be commissioned at the same time as
    Factory New, a jitter must be implemented to allow the TC to process the
    joining procedures of all the devices.

    A joining device without a user interface to configure its joining
    mechanism can be configured to try all the preconfigured keys
    (Install Code, Global Default Centralized Key, and Global Default Distributed Key) upon joining.
    However, if the device is intended only to join networks which only use Install Codes,
    then :code:`zb_secur_ic_set` must be used to set a viable Install Code.

    Touchlink Joining
    -----------------

    Touchlink commissioning is a distributed security joining procedure that requires physical proximity
    and uses its own preconfigured link key.
    For this procedure, a touchlink initiator starts a scan request over all enabled channels
    looking for a touchlink target.
    If a target responds and is selected,
    it will be asked to form a new network for the initiator or join the initiator’s network.

    .. uml::
        :caption: Asking to join with Touchlink commissioning
        :align: center

        @startuml
        group Commissioning
        Initiator->Target: Scan Request
        activate "Target"
        Target-->Initiator: Scan Response
        deactivate "Target"

        Initiator->Initiator: Initiator selects a target to\ncontinue the procedure
        Initiator->Target: Network Join Request
        activate "Target"
        Target-->Initiator: Network Join Response
        deactivate "Target"
        Target->Target: Initiator gets required\nnetwork information
        end

        Initiator->Target: Beacon Request
        activate "Target"
        Initiator->Initiator: Initiator asks for join
        Target-->Initiator: Beacon
        deactivate "Target"

        Initiator->Target: Device Announce
        Initiator->Target: Simple Descriptor Request
        activate "Target"
        Target-->Initiator: Simple Descriptor Response
        deactivate "Target"
        Initiator->Initiator: Initiator establishes binds with common clusters
        @enduml

    .. uml::
        :caption: Asking to start network with Touchlink commissioning
        :align: center

        @startuml
        group Commissioning
        Initiator->Target: Scan Request
        activate "Target"
        Target-->Initiator: Scan Response
        deactivate "Target"

        Initiator->Initiator: Initiator selects a target to\ncontinue the procedure
        Initiator->Target: Network Start Request
        activate "Target"
        Target-->Initiator: Network Start Response
        deactivate "Target"

        Target->Target: Initiator gets required\nnetwork information
        end
        Initiator->Target: Rejoin Request
        activate "Target"
        Initiator->Initiator: Initiator asks for join
        Target-->Initiator: Rejoin Response
        deactivate "Target"

        Initiator->Target: Device Announce
        Initiator->Target: Simple Descriptor Request
        activate "Target"
        Target-->Initiator: Simple Descriptor Response
        deactivate "Target"
        Initiator->Initiator: Initiator establishes binds with common clusters
        @enduml


    Clusters, Commands, and Attributes
    ==================================

    Each application supports a certain number of clusters. Think of a
    cluster as an object containing both methods (commands) and data
    (attributes).

    Each cluster may have zero or more commands. Commands are further
    divided into Server and Client-side commands. Commands cause action, or
    generate a response.

    Each cluster may have zero or more attributes. All of the attributes can
    be found in the main application code file (e.g. :code:`on_off_switch.c` for
    the sample on/off light switch). Attributes describe the current state
    of the device, or provide information about the device, such as whether 
    a light is currently on or off.

    All clusters and attributes are defined either in the Zigbee Cluster
    Library specification.

    Attributes
    ----------

    Attributes are found in a single list called :code:`switch_cfg_attr_list`, in
    the :code:`on_off_switch.c` file. Each attribute entry is initialized to
    a type and value, and contains a pointer to the attribute data.
    Attribute data types can be found in the Zigbee Cluster Library 8 Specification.

    The attributes must be declared using the :code:`ZB_ZCL_DECLARE_BASIC_ATTRIB_LIST( )`
    function during application initialization, one per application endpoint.

    Each attribute has a data type, as defined by Zigbee (such as :code:`UINT8`,
    :code:`INT32`, etc.). Each attribute record contains an attribute type and a
    pointer to the actual data for the attribute. Read-only data can be
    shared across endpoints. Data that is unique to an endpoint (such as the
    OnOff attribute state of the light) should have a unique C variable.

    All attributes can be read. Some attributes can be written. Some
    attributes are reportable (can be automatically sent to a destination
    based on time or change in attribute via the attribute reporting
    functionality). Some attributes are saved as part of a “scene” that can
    later be recalled to set the device to a particular state (such as a
    light on or off). The attribute access is controlled through a field in
    the attribute structure.

    To store an attribute in non-volatile memory (to be preserved across
    reboots) refer to :ref:`sec-application-nv-memory`.

    Adding an Attribute Example
    ---------------------------

    To add an additional attribute to a project, refer to the attributes
    information within the ZCL 8 Specification. Additional attributes can be 
    included through the proper declarations, for example
    :code:`ZB_ZCL_DECLARE_DOOR_LOCK_CLUSTER_ATTRIB_LIST` for a door lock.

    Initializing Clusters
    ---------------------

    For the application to interact with a cluster, the cluster’s compile
    flag must be enabled (if applicable to the cluster) in the project’s
    configuration and the cluster’s source file must be added to the
    project’s Profile to the Workspace.

    Once enabled, the cluster’s callbacks can be registered within the
    application (refer to :ref:`sec-cluster-callback-examples`).

    Cluster Architecture
    --------------------

    All clusters follow the same architecture.

    The cluster library within Z-Stack take care of converting the structures passed from native
    format to over-the-air format, as required by Zigbee. All application
    interaction with clusters takes place in native format.

    They all have the following functions:

    -  **Send** – This group of commands allows various commands to be
    send on a cluster

    -  **ProcessIn** – This function processes incoming commands.

    There is usually one send function for each command. The **Send**
    function has either a set of parameters or a specific structure for the
    command.

    If the application has registered callback functions, then the
    **ProcessIn** will direct the command (after it’s converted to native
    form) to the application callback for that command.

    .. _sec-cluster-callback-examples:

    Cluster Callbacks Example
    -------------------------

    Callbacks are used so that the application can perform the expected
    behavior on a given incoming cluster command. It is up to the
    application to send a response as appropriate. |STACK| provides the
    parsing, but it is up to the application to perform the work.

    A cluster’s callback functions are registered within the application’s
    initialization function by including the application’s endpoint and a
    pointer to the callback record within a register commands callback
    function, :code:`ZB_ZCL_REGISTER_DEVICE_CB`. The commands are registered to 
    their respective callback functions as defined within the cluster’s profile.

    The callback function in an application provides additional processing
    of a command that is specific to that application. These callback
    functions work alongside the response to the incoming command, if a
    response is appropriate.

    Attribute Reporting Functionality
    ---------------------------------

    The Attribute Reporting module takes care of periodically sending the
    ZCL Report Attributes command messages for all reportable attributes
    defined in the application. The module also processes the ZCL Configure
    Reporting and Read Reporting Configuration commands.

    The Attribute Reporting functionality was implemented as described in the ZCL 8 Specification.
    However, in order to optimize the number of Report Attributes command messages sent over the air,
    a consolidation was made for attributes in the same cluster: all reportable attributes of the same cluster share 
    one Minimum Reporting Interval and one Maximum Reporting Interval.
    The shared Minimum Reporting Interval is equal to the lowest of the minimum reporting intervals
    of the cluster’s reportable attributes.
    Similarly, the Maximum Reporting Interval is equal to the lowest of the maximum reporting intervals.

    The Attribute Reporting module automatically looks into the attribute
    definitions registered in the application for all the attributes. Each of these 
    reportable attributes will have a corresponding Attribute Reporting Configuration 
    record later set with some default values. The Attribute Reporting module 
    automatically starts (or stops) the reporting of the attributes in a cluster of 
    an endpoint when the endpoint's bind is added (or removed).

    When the BDB state machine starts commissioning, the Attribute Reporting
    module either loads the previously saved Attribute Reporting Configuration records from NV,
    or finds the application's reportable attributes (from the attribute list) and constructs
    the necessary Attribute Reporting Configuration records.
    Then the module will consolidate the reportable attributes in each cluster of every endpoint,
    in order to trigger the periodic sending of the Report Attributes
    command messages using the Maximum Reporting Interval values.

    .. _z-stack-overview-commissioning:

    Commissioning
    =============

    The BDB commissioning method provides a mechanism to invoke a series of
    procedures that provides the ability to easily connect devices together.
    Depending on the commissioning methods invoked, devices will perform
    actions like forming networks, joining existing networks, and binding
    application endpoints.

    The BDB interface provides an API, :code:`bdb_start_top_level_commissioning`, to 
    trigger one or more commissioning procedures defined as follows:

    .. code-block:: c

    ZB_BDB_INITIALIZATION = 0,
    ZB_BDB_TOUCHLINK_COMMISSIONING = 1,
    ZB_BDB_NETWORK_STEERING = 2,
    ZB_BDB_NETWORK_FORMATION = 4,
    ZB_BDB_FINDING_N_BINDING = 8,

    This commissioning mask is appended to the current commissioning modes being executed.
    The tasks are also executed with the priority listed above
    (TL as initiator first, then Nwk steering, then Formation, and lastly Finding and Binding).
    The priority of the tasks are checked when the current task is finished.
    The tasks can be appended at any time (e. g. in response to a commissioning notification).
    For example, suppose Nwk steering and Formation are requested. Nwk steering will start running.
    If TL as initiator is requested before Nwk steering is finished,
    then TL as initiator will start after Nwk steering is finished but before Formation starts.

    .. _sec-bdb-notifications:

    BDB Notifications
    -----------------

    The application will receive BDB notifications from the stack automatically and
    will have the ID :code:`zstackmsg_CmdIDs_BDB_NOTIFICATION`.
    The application can trigger another commissioning method upon receiving
    a certain notification. For example, a router device may start network steering
    to search for a suitable network and count the number of times this process
    fails. If this process fails ‘x’ times in a row, then it may decide to change
    the channel mask to search networks in other channels or to form its own network.
    The full API is described in |ZSTACK_API|.

    The notifications are called when certain tasks start or finish.
    Different logical devices may handle and interpret the notifications differently.

    Every notification will have a pointer to a structure of type
    :code:`bdbCommissioningModeMsg_t`, which contains the commissioning mode being
    reported, the status, and the mask of the remaining commissioning modes
    to be executed. The notifications (commissioning modes and statuses) are defined in
    :code:`bdb_interface.h`. The same information is documented in the following table.

    +-----------------------------------------------------+----------------------------------------------------+-------------------------------------------------------------+
    | Commissioning mode (**BDB\_COMMISSIONING\_mode**)   | Status reported (**BDB\_COMMISSIONING\_status**)   | Description                                                 |
    +-----------------------------------------------------+----------------------------------------------------+-------------------------------------------------------------+
    | **INITIALIZATION**                                  | **NETWORK\_RESTORED**                              | Only send if the device did restore its network parameters. |
    |                                                     |                                                    | On end devices, if no parent is found with the restored     |
    |                                                     |                                                    | network parameters, a *Parent Lost* mode is with status     |
    |                                                     |                                                    | *No Network* is notified.                                   |
    +-----------------------------------------------------+----------------------------------------------------+-------------------------------------------------------------+
    | **NWK\_STEERING** (for Router and End Devices)      | **IN\_PROGRESS**                                   | Notifies when network steering is started (only if the      |
    |                                                     |                                                    | device is not in a network, otherwise reports *success*)    |
    |                                                     +----------------------------------------------------+-------------------------------------------------------------+
    |                                                     | **NO\_NETWORK**                                    | No suitable network was found in primary channel or         |
    |                                                     |                                                    | secondary channel masks or the joining process did fail in  |
    |                                                     |                                                    | the attempted networks.                                     |
    |                                                     +----------------------------------------------------+-------------------------------------------------------------+
    |                                                     | **TCLK\_EX\_FAILURE**                              | The device successfully joined the network, but could not   |
    |                                                     |                                                    | perform the Trust Center Link Key exchange process. The     |
    |                                                     |                                                    | device will reset to factory new after this notification is |
    |                                                     |                                                    | reported to the application.                                |
    |                                                     +----------------------------------------------------+-------------------------------------------------------------+
    |                                                     | **SUCCESS**                                        | The device is now on a network and broadcasted a Management |
    |                                                     |                                                    | Permit Joining ZDO frame.                                   |
    +-----------------------------------------------------+----------------------------------------------------+-------------------------------------------------------------+
    | **NWK\_STEERING** (for Coordinators)                | **NO\_NETWORK**                                    | The device is not on a network, so it cannot perform this   |
    |                                                     |                                                    | action.                                                     |
    |                                                     +----------------------------------------------------+-------------------------------------------------------------+
    |                                                     | **SUCCESS**                                        | The device is in a network and has broadcasted a Management |
    |                                                     |                                                    | Permit Joining ZDO frame.                                   |
    +-----------------------------------------------------+----------------------------------------------------+-------------------------------------------------------------+
    | **FORMATION**                                       | **IN\_PROGRESS**                                   | Notifies when formation process is started.                 |
    |                                                     +----------------------------------------------------+-------------------------------------------------------------+
    |                                                     | **SUCCESS**                                        | The network has been created successfully.                  |
    |                                                     +----------------------------------------------------+-------------------------------------------------------------+
    |                                                     | **FORMATION\_FAILURE**                             | The device could not create the network with the given      |
    |                                                     |                                                    | parameters.                                                 |
    +-----------------------------------------------------+----------------------------------------------------+-------------------------------------------------------------+
    | **FINDING\_BINDING**                                | **FB\_TARGET\_IN\_PROGRESS**                       | Indicates the start of the Finding and Binding as target. No|
    |                                                     |                                                    | notification is given by this callback when the process ends|
    |                                                     +----------------------------------------------------+-------------------------------------------------------------+
    |                                                     | **FB\_INITITATOR\_IN\_PROGRESS**                   | Indicates the start of the Finding and Binding as Initiator.|
    |                                                     +----------------------------------------------------+-------------------------------------------------------------+
    |                                                     | **FB\_NO\_IDENTIFY\_QUERY\_RESPONSE**              | After complete the Finding and Binding process as initiator |
    |                                                     |                                                    | (single attempt of periodic attempt), no identify query     |
    |                                                     |                                                    | responses were received.                                    |
    |                                                     +----------------------------------------------------+-------------------------------------------------------------+
    |                                                     | **FB\_BINDING\_TABLE\_FULL**                       | During the Finding and Binding process the binding table got|
    |                                                     |                                                    | full, so the process stops and no additional binds can be   |
    |                                                     |                                                    | added.                                                      |
    |                                                     +----------------------------------------------------+-------------------------------------------------------------+
    |                                                     | **FAILURE**                                        | No endpoint was found to perform Finding and Binding, or the|
    |                                                     |                                                    | endpoint did not have implemented the Identify cluster      |
    |                                                     |                                                    | properly.                                                   |
    +-----------------------------------------------------+----------------------------------------------------+-------------------------------------------------------------+
    | **TOUCHLINK**                                       | **TL\_TARGET\_FAILURE**                            | A node has not joined a network when requested during       |
    |                                                     |                                                    | touchlink.                                                  |
    |                                                     +----------------------------------------------------+-------------------------------------------------------------+
    |                                                     | **TL\_NOT\_AA\_CAPABLE**                           | The initiator is not address assignment capable during      |
    |                                                     |                                                    | touchlink                                                   |
    |                                                     +----------------------------------------------------+-------------------------------------------------------------+
    |                                                     | **TL\_NO\_SCAN\_RESPONSE**                         | No response to a Scan Request inter-PAN command has been    |
    |                                                     |                                                    | received during touchlink                                   |
    |                                                     +----------------------------------------------------+-------------------------------------------------------------+
    |                                                     | **TL\_NOT\_PERMITTED**                             | A touchlink steal attempt was made when a node is already   |
    |                                                     |                                                    | connected to a centralized security network.                |
    +-----------------------------------------------------+----------------------------------------------------+-------------------------------------------------------------+
    | **PARENT\_LOST** (Only for End Devices)             | **NO\_NETWORK**                                    | This is notified if the end device does lose contact with   |
    |                                                     |                                                    | the parent device or if after initialization it cannot find |
    |                                                     |                                                    | a parent device in the commissioned network.                |
    |                                                     +----------------------------------------------------+-------------------------------------------------------------+
    |                                                     | **NETWORK\_RESTORED**                              | Notification that a suitable parent device got found and the|
    |                                                     |                                                    | rejoin process was successful.                              |
    +-----------------------------------------------------+----------------------------------------------------+-------------------------------------------------------------+

    Initialization Procedure
    ------------------------

    The BDB interface will perform an initialization when :code:`Zstackapi_bdbStartCommissioningReq()`
    is called after a power cycle. Any commissioning mode mask may be used,
    and the power cycle is detected by the global RAM variable :code:`bdb_initialization`.
    If the attribute :code:`bdbNodeIsOnANetwork` is :code:`TRUE`,
    the initialization procedure retrieves the network parameters from NV.
    Coordinator and router devices will rejoin the network and resume operations as if they never left.
    Upon rejoining, they will send and process parent annce messages (see :ref:`sec-parent-annce`).
    End devices will restore the network parameters and try to perform a rejoin on
    any parent available in the same network only one time.
    This procedure is illustrated in :numref:`fig-initialization-restore-router-coordinator` and 
    :numref:`fig-initialization-restore-end-device`.

    .. _fig-initialization-restore-router-coordinator:
    .. uml::
        :caption: Initialization Procedure for a Router/Coordinator
        :align: center

        @startuml
        skinparam defaultTextAlignment center
        :Begin;
        if (Is bdb_initialization = FALSE?) then (Yes)
            if (Is bdbNodeIsOnANetwork = TRUE?) then (Yes)
            :Restore network parameters]
            :Notify NETWORK_RESTORED/
            else (No)
            endif
        else (No)
        endif
        :End;
        @enduml

    .. _fig-initialization-restore-end-device:
    .. uml::
        :caption: Initialization Procedure for a End Device
        :align: center

        @startuml
        skinparam defaultTextAlignment center
        :Begin;
        if (Is bdb_initialization = FALSE?) then (Yes)
            if (Is bdbNodeIsOnANetwork = TRUE?) then (Yes)
            :Restore network parameters]
            :Attempt rejoin to any parent with the network parameters restored]
            if (Suitable parent device found with the network parameters?) then (Yes)
            :Notify NETWORK_RESTORED/
            else (No) 
            :Notify PARENT_LOST/
            endif
            else (No)
            endif
        else (No)
        endif
        :End;
        @enduml

    .. _z-stack-overview-parent-lost:

    Parent Lost
    -----------

    If an end device loses contact with its parent device
    or is reset while joined to a network,
    the BDB module will send the application a
    :code:`BDB_COMMISSIONING_PARENT_LOST` notification,
    after which the end device cannot perform any other commissioning method.
    The device must either restore its network or
    reset to factory new and be commissioned again.
    To restore the network, the device must call
    :code:`Zstackapi_bdbZedAttemptRecoverNwkReq()`,
    which performs a single active scan in the network for a suitable parent
    (same Extended PAN ID and child device capacity).
    This means that the device sends a single beacon request.
    If no suitable parent device is found, then
    another :code:`BDB_COMMISSIONING_PARENT_LOST` notification is sent to the application.
    The application is responsible for attempting to restore the network.
    The interval between these attempts should increase to reduce power consumption.
    If Finding and Binding was in progress when the device lost its parent,
    it will keep running and resume its operation for the remaining time after the device restores its operation.

    Network Steering Procedure for a Node on a Network
    --------------------------------------------------

    If network steering is invoked by a device that is already on a network
    (:code:`bdbNodeIsOnANetwork` set to :code:`TRUE`), it will broadcast a permit joining
    request for 180 seconds (:code:`BDBC_MIN_COMMISSIONING_TIME`), after which
    the device will notify the application of :code:`BDB_COMMISSIONING_SUCCESS`.

    .. uml::
        :caption: Network Steering Procedure for a Node On a Network
        :align: center

        @startuml
        skinparam defaultTextAlignment center
        :Start;
        :Broadcast ZDP_MgmtPermitJoinReq]
        if (Logical Type ZC/ZR?) then (Yes)
        :Enable permit join for ≥\nBDBC_MIN_COMMISSIONING_TIME;
        else (No)
        endif
        :Notify SUCCESS/
        :End;
        @enduml

    .. _z-stack-overview-nwk-steering-not-on-nwk:

    Network Steering Procedure for a Node not on a Network
    ------------------------------------------------------

    This procedure is performed when Network Steering is requested and the
    device is not on a network (:code:`bdbNodeIsOnANetwork` set to :code:`FALSE`).
    This will cause the device to start looking for suitable networks to join. The
    procedure is illustrated in :numref:`fig-nwk-steering-not-in-a-network` and
    described as follows:

    1. The device will perform a scan in all channels defined in
    :code:`BDB_DEFAULT_PRIMARY_CHANNEL_SET`, searching for any suitable
    network and creating a network descriptor list of the networks found.

    a. The application will receive a :code:`zstackmsg_CmdIDs_BDB_FILTER_NWK_DESCRIPTOR_IND`
        message, which contains a list of network descriptors of the networks found 
        during the scan. It can use Zstackapi_bdbNwkDescFreeReq() to remove network 
        descriptors of networks that it will not attempt to join.

    b. If no suitable networks are found or the device cannot perform
        joining on the networks found (association was not successful or
        could not get the network key), then the device will proceed to perform
        the same steps but with the channel mask defined in
        :code:`BDB_DEFAULT_SECONDARY_CHANNEL_SET`.

    c. Only non-zero channel masks are used for network discovery.

    2. The BDB state machine will try to perform association and
    authentication in the suitable networks discovered using the security
    keys for Centralized networks (default key or Install Code) or
    Distributed networks as defined in :ref:`z-stack-overview-security`. For Centralized
    networks it will also perform the TCLK exchange.

    3. If the joining procedure is completed, then the joining device will broadcast a permit joining request
    to refresh the joining timeout for other devices trying to join simultaneously.
    The network manager can close the network for joining by sending a permit join request with timeout = 0.

    .. _fig-nwk-steering-not-in-a-network:
    .. uml::
        :caption: Network Steering Procedure for a Node Not on a Network
        :align: center

        @startuml
        skinparam defaultTextAlignment center
        :Start;
        :Notify IN_PROGRESS/
        :Nwk discovery over \nbdbPrimaryChannelSet]
        :A;
        if (Was discovery \nsuccessful?) then (Yes)
            :Determine a list of \nsuitable networks]
            if (Was a suitable \nnwk found?) then (Yes)
                :B;
                :Try MAC association]
                if (Was the join successful?) then (Yes)
                    :Wait for nwk key]
                    if (Was the nwk key received successfully?) then (Yes)
                        :Broadcast device announce]
                        if (Is the TC addr = 0xFFFFFFFFFFFFFFFF?) then (No)
                            :Retrieve a new TCLK|
                            if (Was the nwk key received successfully?) then (No)
                                :Leave the nwk and reset nwk parameters]
                                :Notify TCLK_EX_FAILURE/
                                :End;
                                detach
                            else (Yes)
                            endif
                        else (Yes)
                        endif
                    :Broadcast ZDP_MgmtPermitJoinReq]
                    :Notify SUCCESS/
                    :End;
                    detach
                    else (No)
                    :Reset nwk parameters]
                    :C;
                    detach
                    endif
                else (No)
                    :C;
                    if (More networks to try?) then (Yes)
                        :B;
                        detach
                    else (No)
                        :D;
                        detach
                    endif
                endif
            else (No)
                :D;
                detach
            endif
        else (No)
            :D;
            if (Is bdbSecondaryChannelSet = 0 \nor has already been attempted?) then (Yes)
                :Notify NO_NETWORK/
                :End;
                detach
            else (No)
                :Nwkdiscovery over \nbdbSecondaryChannelSet]
                :A;
                detach
        endif
        @enduml

    Network Formation
    -----------------

    This procedure defines the steps to take when a device with formation
    capabilities is instructed to form a network (coordinator or router). If
    an end device is instructed to perform formation, then it will report a
    failure.

    The formation process for devices with formation capabilities consists
    of a first attempt to create the network in any of the channels selected
    in the primary channel mask, and if for any reason it cannot perform the
    formation in those channels (channel mask invalid or selected PAN ID
    already found in the same channel) the device will try to perform
    formation in the secondary channel mask. If both of these procedures
    fail, it will report a :code:`BDB_COMMISSIONING_FORMATION_FAILURE` to the
    application. If formation is performed successfully then a
    :code:`BDB_COMMISSIONING_FORMATION_SUCCESS` is sent instead.
    After a successful network formation,
    the application can open the network for joining with the network steering procedure.

    .. uml::
        :caption: Network Formation
        :align: center

        @startuml
        skinparam defaultTextAlignment center
        :Start;
        :Notify IN_PROGRESS/
        :Network Discovery over\nbdbPrimaryChannelSet]
        while (Formation Successful?) is (No)
        if (Is bdbSecondaryChannelSet=0?\nOr has already been attempted?) then (Yes)
            :Notify FORMATION_FAILURE/
            :End;
            detach
        else (No)
            :Network Discovery over\nbdbSeconaryChannelSet]
        endif
        endwhile (Yes)
        if (Logical Type ZC?) then (Yes)
        :Initiate Trust Center\nfunctionality]
        else (No)
        endif
        :Notify SUCCESS;
        :End;
        @enduml

    .. _z-stack-overview-finding-binding:

    Finding and Binding
    -------------------

    The Finding and Binding procedure can be performed as initiator, target, or both,
    depending on the clusters of the endpoint performing the Finding and Binding procedure.
    For example, if an endpoint has a cluster that is meant to be initiator,
    the Finding and Binding process for this endpoint will be executed as initiator.
    The definitions for initiator or target on clusters can be found in Zigbee ZCL 7 Specification.

    The application must specify with which endpoint it wants to perform the
    finding and binding procedure by calling :code:`Zstackapi_bdbSetIdentifyActiveEndpointReq()`.
    Note that the endpoint indicated must contain the Identify cluster in order
    to perform the procedure.

    Finding & Binding Procedure for a Target Endpoint
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    When finding and binding is triggered on a target endpoint, the endpoint
    identifies itself for a finite period of time and handles the identify
    query commands from the initiator device.
    This commissioning procedure sends a :code:`BDB_COMMISSIONING_FB_INITIATOR_IN_PROGRESS`
    notification when it starts and a zstackmsg :code:`zstackmsg_CmdIDs_BDB_IDENTIFY_TIME_CB` when it finishes.

    .. uml::
        :caption: Finding & Binding Procedure for a Target Endpoint
        :align: center

        @startuml
        skinparam defaultTextAlignment center
        :Begin;
        :Notify FB_INITIATOR_IN_PROGRESS/
        :Enable permit join for ≥
        BDBC_MIN_COMMISSIONING_TIME]
        repeat
        :Handle Identify Query Request]
        repeat while (Identify Time Expired?) is (No)
        ->Yes;
        :End;
        @enduml

    Finding and Binding Procedure for an Initiator Endpoint
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    In this procedure, the initiator will search for identifying endpoints
    by broadcasting identify query commands and requesting a simple descriptor for each node found.
    Then the binds for matching application clusters are created in the initiator.
    If group bind is requested, the initiator endpoint configures a group membership of the target endpoints.

    The finding and binding process for an initiator device is illustrated
    in :numref:`fig-finding-binding-initiator` and described here:

    1. The application is notified about the commissioning method starting,
    and the local device broadcasts an Identify Query command.

    a. If no identify query responses are received over the process, then
        the application receives a :code:`BDB_COMMISSIONING_FB_NO_IDENTIFY_QUERY_RESPONSE` and the process finishes.

    b. If the device receives one or more responses then the device
        creates a list of the device responses (respondent devices).

    2. The local device sends a ZDO simple descriptor request to each respondent device one at a time.
    If no response is received, the local device will send a ZDO simple descriptor request
    to the next respondent in the list.
    If no response from a respondent is received after FINDING_AND_BINDING_MAX_ATTEMPTS attempts,
    the local device marks that respondent as completely processed.
    This step repeats until all respondents are completely processed.

    3. Upon the reception of a simple descriptor response,
    the local device will search for application clusters compatible with the endpoint in the local device
    that is performing the Finding and Binding procedure.

    4. If the device is performing unicast binds (:code:`BDB_DEFAULT_COMMISSIONING_GROUP_ID == 0xFFFF`),
    it searches for the IEEE address of the respondent device in the address manager.
    If not found, it sends a ZDO IEEE address request command.
    The device reattempts this process until the IEEE address response is received from the respondent
    and the bind entry is created for the matching clusters.
    After FINDING_AND_BINDING_MAX_ATTEMPTS attempts, this respondent is marked as processed without adding any bind.
    Group binds are created if any match is found.
    For the definition of application clusters, refer to the Zigbee ZCL 7 Specification. 

    a. The application will receive bind notifications via a zstackmsg of ID
        :code:`zstackmsg_CmdIDs_BDB_BIND_NOTIFICATION_CB`.

    b. If the bind table gets full during this process the application
        will receive a :code:`BDB_COMMISSIONING_FB_TABLE_FULL` notification and
        the process will be finished.

    5. The local device will repeat steps 2 to 4 until all respondents are marked as processed.
    Then it will send a :code:`BDB_COMMISSIONING_SUCCESS` notification to the application.

    The Finding and Binding procedure for groups enables APS Acknowledgements
    to increase reliability of creating the group membership at the remote device.

    The finding and binding process for an initiator device can be
    configured to perform periodically every
    :code:`FINDING_AND_BINDING_PERIODIC_TIME` seconds instead of
    :code:`BDBC_MIN_COMMISSIONING_TIME` (180) seconds. This configuration is determined by
    :code:`FINDING_AND_BINDING_PERIODIC_ENABLE` (default value is
    :code:`TRUE`).
    In this case, multiple identify query command responses from the same device
    will not be duplicated in the respondent list.
    The Finding and Binding process can be terminated early
    by calling :code:`Zstackapi_bdbStopInitiatorFindingBindingReq()`.

    .. _fig-finding-binding-initiator:
    .. uml::
        :caption: Finding & Binding Procedure for an Initiator Endpoint
        :align: center

        @startuml
        skinparam defaultTextAlignment center
        :Begin;
        :Notify FB_TARGET_IN_PROGRESS/
        :Broadcast identify query]
        if (Identify Query Response received?) then (Yes)
        repeat
        :Request Simple Descriptor for the next endpoint]
        if (Valid Simple Descriptor Response received?) then (Yes)
            repeat
            if (Next Cluster Match?) then (Yes)
                :Attempt creating entry in Binding Table
                with next matching cluster]
                if (Binding Table full?) then (Yes)
                :Notify BINDING_TABLE_FULL/
                :End;
                detach
                else (No)
                endif
            else (No)
            endif
            repeat while (Other Clusters to try?) is (Yes)
            ->No;
            :Configure bdbCommissioningGroupID Group
            on the respondent]
        else (No)
        endif
        repeat while (Other Endpoints to try?) is (Yes)
        ->No;
        :Notify SUCCESS/
        else (No)
        :Notify NO_IDENTIFY_QUERY_RESPONSE/
        endif
        :End;
        @enduml

    .. _z-stack-overview-touchlink-commissioning:

    Touchlink Commissioning
    -----------------------

    Touchlink commissioning is an optional commissioning mechanism defined in the Zigbee BDB specification,
    where nodes are commissioned using inter-PAN communication. It requires physical proximity between devices.

    Configurations
    ~~~~~~~~~~~~~~

    The configurations in the following sections must be modified by the user to create a
    valid Touchlink device. They are all found in the file :code:`bdb_interface.h` except for the assignment
    of :code:`BDB_TL_INITIATOR` and :code:`BDB_TL_TARGET` modes which are selected through the SysConfig
    *RF STACKS* |rarr| *Z-Stack* |rarr| *Touchlink Commissioning Endpoint* interface.

    Key Installation
    ^^^^^^^^^^^^^^^^

    All commercial Touchlink products use the “Touchlink master key” and the
    “Touchlink pre-installed link key” set. This set of keys could be
    available to manufacturers which have a successfully certified Touchlink product,
    using the certification keys set provided by default.

    Note that any Touchlink implementation will not be able to interoperate
    with commercial Touchlink devices without the Touchlink master keys.
    Once the Touchlink master keys have been achieved, they should be
    installed in the code with the following modifications:

        1. Overwrite the :code:`TOUCHLINK_CERTIFICATION_ENC_KEY` and 
        :code:`TOUCHLINK_CERTIFICATION_LINK_KEY` with the actual secret
        values.

        2. Change the :code:`TOUCHLINK_KEY_INDEX` definition to
        :code:`TOUCHLINK_KEY_INDEX_MASTER`.

    Constants
    ^^^^^^^^^

    The BDB defines constants and internal attribute defaults to allow a
    device to manage how the Touchlink device operates (see
    Base Device Behavior Specification).

    +-------------------------------------------+------------------------------------+--------------+
    | **Definition**                            | **Specification’s Constant /       | **Value**    |
    |                                           | Attribute default**                |              |
    +===========================================+====================================+==============+
    | BDBCTL\_INTER\_PAN\_TRANS\_ID\_LIFETIME   | *bdbcTLInterPANTransIdLifetime*    | 8000         |
    +-------------------------------------------+------------------------------------+--------------+
    | BDBCTL\_MIN\_STARTUP\_DELAY\_TIME         | *bdbcTLMinStartupDelayTime*        | 2000         |
    +-------------------------------------------+------------------------------------+--------------+
    | BDBCTL\_PRIMARY\_CHANNEL\_LIST            | *bdbcTLPrimaryChannelSet*          | 0x02108800   |
    +-------------------------------------------+------------------------------------+--------------+
    | BDBCTL\_RX\_WINDOW\_DURATION              | *bdbcTLRxWindowDuration*           | 5000         |
    +-------------------------------------------+------------------------------------+--------------+
    | BDBCTL\_SCAN\_TIME\_BASE\_DURATION        | *bdbcTLScanTimeBaseDuration*       | 250          |
    +-------------------------------------------+------------------------------------+--------------+
    | BDBCTL\_SECONDARY\_CHANNEL\_LIST          | *bdbcTLSecondaryChannelSet*        | 0x05EF7000   |
    +-------------------------------------------+------------------------------------+--------------+

    Endpoint Setup
    ^^^^^^^^^^^^^^

    Since the Touchlink commissioning is managed by a dedicated task separate from the applications,
    its endpoint and device ID may be re-defined.
    The endpoint must be a valid value that is not used by the device’s other endpoints.
    The device ID must not equal any valid device ID (to prevent accidental matches).  By default,
    :code:`TOUCHLINK_INTERNAL_ENDPOINT` is 13 and :code:`TOUCHLINK_INTERNAL_DEVICE_ID` is = 0xE15E.

    Identify Sequence Time Interval
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    In the Touchlink commissioning sequence, if an appropriate scan response
    command is received, the initiator will send an Identify command to the
    chosen target and then wait for a time interval defined by :code:`BDB_TL_IDENTIFY_TIME`
    (in milliseconds) before sending a network start or network join command.

    When an Identify Request command is received with identify duration
    field value set to 0xffff (default time known by the receiver), the
    application’s Identify callback function will be called with a duration
    value set according to the :code:`TOUCHLINK_DEFAULT_IDENTIFY_TIME` (default 3 seconds):

    It is possible to gracefully abort a touch-link process (see
    Base Device Behavior Specification), until the end of this time
    interval. Beyond that, target state may change irreversibly. If abort is
    employed and controlled by a human interaction, it is recommended to
    increase this value (e.g. to 2000). Please note that increasing it to a
    higher value than the default also increases the risk of atouch-link
    failure due to transaction lifetime expiration, especially if done on
    the secondary channel set.

    Free Ranges Split Thresholds
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    When initiating Touchlink commissioning with devices which are capable
    of assigning addresses, ranges of free network addresses and group
    identifiers held by the initiator could be split and passed to the
    target.

    The initiator can split its ranges as long as the remaining range and
    the target range are no less than the minimum size, defined by
    :code:`TOUCHLINK_ADDR_THRESHOLD` (the minimum size of addresses range,
    default 10) and :code:`TOUCHLINK_GRP_ID_THRESHOLD` (the minimum size 
    of group identifiers range, default 10).

    Application Selective Target TouchLink 
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    This feature allows overriding the default RSSI-based target selection
    during Touchlink with an application-specific selection function. An
    application selection function could be used in scenarios where multiple
    targets are expected to have similar RSSI (e.g. multiple lights bundled
    together), and allows integrating other parameters in the selection
    (e.g. Factory New state, previously selected device, etc.).

    Development-Only Parameters
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~

    The following parameters, if enabled, will break Touchlink conformity
    and security rules. They may be used to assist during development, but
    must be disabled before release. All the parameters could be uncommented
    in :code:`bdb.h` file, instead of being defined globally in the project.

    Channel Offset
    ^^^^^^^^^^^^^^

    The flags :code:`Ch_Plus_1`, :code:`Ch_Plus_2`, or :code:`Ch_Plus_3` can be set in the
    :code:`TOUCHLINK_CH_OFFSET` definition in :code:`bdb.h` to shift the primary channel set,
    which will allow testing of multiple Touchlink devices
    set in the same space without interference.
    This should be used for testing purposes only.
    :code:`TOUCHLINK_CH_OFFSET` is defined by default as :code:`No_Ch_offset`, 
    which means that no shift is applied to the primary channel set.

    Fixed First Channel Selection
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    The flag :code:`TOUCHLINK_DEV_SELECT_FIRST_CHANNEL`, if enabled during
    compilation, will override the random channel selection mechanism
    employed by the Touchlink device, and will set it to always select the
    first primary channel.

    Touchlink Commissioning Procedure for an Initiator
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    In this procedure the initiator scans for nodes that support touchlink,
    and if any are found, the touchlink commissioning procedure establishes
    a new distributed network with the target.

    .. uml::
        :caption: Touchlink Commissioning Procedure for an Initiator
        :align: center

        @startuml
        skinparam defaultTextAlignment center
        :Begin;
        :Notify IN_PROGRESS/
        :Send scan request over bdbPrimaryChannelSet]
        while (Is primary scan done or bdbSecondaryChannelSet = 0?) is (Yes)
            :Send scan request over bdbPrimaryChannelSet]
        endwhile (No)
        if (Valid scan response received?) then (Yes)
            :Determine the list of potential targets]
            :Optionally send device information or identity]
            if (Is the target on the same \nnetwork as the initiator?) then (Yes)
                :Update target or \ninitiator nwkUpdated and \nchannel as necessary]
                :A;
                detach
            else (No)
                if (Is the initiator on a \ncentralized nwk?) then (Yes)
                    :Notify TL_NOT_PERMITTED/
                    detach
                else (No)
                    if (Is the initiator addr \nassignment capable?) then (Yes)
                        :Notify TL_NOT_AA_CAPABLE/
                        detach
                    else (No)
                        :Node on a network;
                        detach
                    endif
                endif
            endif
        else (No)
            :Notify TL_NO_SCAN_RESPONSE/
            :End;
            detach
        endif
        detach
        :Node on a network;
        if (bdbNodeIsOnANetwork = TRUE?) then (Yes)
            :B;
            detach
        else (No)
        if (Logical type router?) then (Yes)
            :Start a new network]
            :B;
            :Send network join router/end device command]
            if (Valid network join response received?) then (Yes)
                :Wait for the target to join the network]
                :A;
                detach
            else (No)
                :Notify TL_TARGET_FAILURE/
                :End;
                detach
            endif
        else (No)
            if (Is the target a router?) then (Yes)
                :Send network start request]
                if (Valid network start \nresponse received?) then (Yes)
                    :Copy the network parameters \nand wait for the network to start]
                    if (Logical type End device?) then (Yes)
                        :Rejoin the network]
                        :A;
                        :Send simple descriptor \nto establish binds]
                        :Notify success/
                        :End;
                        detach
                    else (No)
                        :A;
                        detach
                    endif
                else (No)
                    :D;
                    :Notify TL_NO_NETWORK/
                    :End;
                    detach
                endif
            else (No)
                :D;
                detach
            endif
        endif
        @enduml

    Touchlink Commissioning Procedure for a Target
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    In this procedure, the target responds to touchlink commissioning
    commands from the initiator to start a new network or to join the
    initiator network.

    .. uml::
        :caption: Touchlink Commissioning Procedure for a Target
        :align: center

        @startuml
        skinparam defaultTextAlignment center
        :Start;
        if (Scan request received?) then (Yes)
            if (RSSI greater than or equal to product specific threshold?) then (Yes)
                :Start transaction timer and send scan response back to the initiator]
                :A;
                if (Touchlink Commissioning received within timeout) then (Yes)
                    split
                        :Other Touchlink \nCommissioning requests;
                        detach
                    split again
                        :Network start req/
                        if (Logical type Router?) then (Yes)
                            if (Start a network?) then (Yes)
                                :Determine network parameters]
                                :Send network start response success]
                                :Leave the old network in fot factory new]
                                :Start the network]
                                :Direct join the initiator]
                                :B;
                                :Setup link key information]
                                :End;
                                detach
                            else (No)
                                :Identify device]
                                :End;
                                detach
                            endif
                        else (No)
                            :A;
                            detach
                        endif
                    split again
                        :Network join reouter/end device req/
                        if (Logical type is the appropriate?) then (Yes)
                            if (Join the network?) then (Yes)
                                :Send network join \nrouter/end device response]
                                :Leave old network \nif not factory new]
                                :Copy the network parameters and \nstart operating on the network]
                                :B;
                                detach
                            else (No)
                                :Identify device]
                                :End;
                                detach
                            endif
                        else (No)
                            :A;
                            detach
                        endif
                    end split
                endif    
            endif
        endif
        :End;
        detach
        :Other Touchlink \nCommissioning requests;
        split
            split
                :TransID doesn't match/
            split again
                :Device information request/
                :Send device information \nresponse back to the initiator]
            split again
                :Identify request/
                :Identify device]
            split again
                :Network update request/
                :Update nwkUpdateId \nas necessary]
            end split
            :A;
            detach
        split again
            :Reset to factory new request/
            :Reset the device|
            :End;
            detach
        end split
        @enduml

    .. _sec-reset-procedures:

    Reset Procedures
    ----------------

    Base device behavior defines how the device must act upon reception of
    reset commands over-the-air or by user interaction as follows:

    Reset via Basic Cluster
    ~~~~~~~~~~~~~~~~~~~~~~~

    If the application’s Basic Cluster supports reset commands,
    then the application must reset all attributes in every cluster supported by the device.
    This command must not affect any network parameters, binds, or groups.
    The application implements this in the callback function for this command.

    Reset via Touchlink Commissioning Cluster
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    If touchlink as target is supported, then this reset mechanism will trigger the device
    to issue a leave request for itself with *Rejoin* set to :code:`FALSE` and *RemoveChildren* set to :code:`FALSE`. 
    See :ref:`sec-leave-request` for further details on the leave request.

    Reset via Mgmt\_leave\_req ZDO command
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    If the command is valid, then the receiving device will issue a leave request for itself
    with *Rejoin* set to :code:`FALSE` and *RemoveChildren* set to :code:`FALSE`.
    See :ref:`sec-leave-request` for further details on the leave request.

    Reset via Local Action
    ~~~~~~~~~~~~~~~~~~~~~~

    This type of reset is triggered by the user (eg. a button press).
    Non-Coordinator devices will issue a network leave request for itself
    with *Rejoin* set to :code:`FALSE` and *RemoveChildren* set to :code:`FALSE`.
    Coordinator devices will clear persistent Zigbee data (since they cannot process network leave commands).
    See :ref:`sec-leave-request` for further details on leave requests.
    The application may trigger this reset by calling :code:`Zstackapi_bdbResetLocalActionReq()`.

    .. _sec-leave-request:

    Reset via Network Leave Request
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Network leave requests are processed differently across device types.
    Coordinator devices ignore the command (including those it issues for itself).
    Router devices process leave requests issued by itself and any other device in the network
    (if :code:`zgNwkLeaveRequestAllowed` is enabled).
    End devices only accept leave requests issued by itself and or its parent device.
    A valid request will cause the device to clear all persistent Zigbee data
    (bindings, network parameters, groups, attributes, etc.)
    except the outgoing network frame counter for the network it is leaving.

    .. _sec-network-manager:

    Network Manager
    ===============

    Overview
    --------

    A single routing device can become the Network Manager by defining :code:`NWK_MANAGER` inside the 
    Project Properties. This device is responsible for receiving channel interference reports 
    and PAN ID conflict reports. Based on these reports, the Network Manager changes the network 
    channel and PAN ID as needed.

    The default address of the Network Manager is the coordinator. However,
    this can be updated by sending a :code:`Zstackapi_ZdoMgmtNwkUpdateReq` command with a
    different short address for the Network Manager. The device that is the
    Network Manager sets the network manager bit in the server mask in the
    node descriptor and responds to :code:`Zstackapi_ZdoServerDiscReq`
    commands.

    The Network Manager implementation resides in :code:`zd_nwk_mgr.c` and
    :code:`zd_nwkmgr.h` files.

    Channel Interference
    --------------------

    The Network Manager implements frequency agility measures if interference is detected.
    This section explains how the channel of a network can be changed using
    :code:`Mgmt_NWK_Update_req` commands and :code:`Mgmt_NWK_Update_notify` events.

    Channel Interference Detection
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    The coordinator and all routers transmit failures using the Transmit Failure field in their neighbor tables.
    They also keep a NIB counter for total transmissions attempted.
    If this counter exceeds :code:`ZDNWKMGR_MIN_TRANSMISSIONS` (20)
    and the number of transmit failure is greater than :code:`ZDNWKMGR_CI_TX_FAILURE` (25) percent
    of the messages sent, the device may have detected interference on the current channel.

    The device then takes the following steps:

    1. Conduct an energy scan on all channels. If this energy scan does not
    indicate higher energy on the current channel than other channels, no
    action is taken. The device should continue to operate as normal and
    the message counters are not reset.

    2. If the energy scan does indicate increased energy on the channel in
    use, a :code:`Mgmt_NWK_Update_notify` should be sent to the Network
    Manager to indicate that interference is present. This report is sent as
    an APS unicast with acknowledgement, and once the acknowledgment is
    received, the total transmit and transmit failure counters are reset
    to zero.

    3. To avoid a device with communication problems from constantly sending
    reports to the Network Manager, the device does not send a
    :code:`Mgmt_NWK_Update_notify` more than 4 times per hour.

    Channel Interference Resolution
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Upon receipt of an unsolicited :code:`Mgmt_NWK_Update_notify`, the Network
    Manager applies different methods to best determine when a channel
    change is required and how to select the most appropriate channel.

    The Network Manger does the following:

    1. Upon receipt of the :code:`Mgmt_NWK_Update_notify`, the Network Manager
    determines if a channel change is required using the following
    criteria:

    a. If any single device has more than :code:`ZDNWKMGR_CC_TX_FAILURE` (50)
        percent transmission failures, then a channel change should be
        considered.

    b. The Network Manager compares the failure rate reported on the
        current channel against the stored failure rate from the last
        channel change. If the current failure rate is higher than the
        last failure rate, then the channel change is considered.

    2. If the above data indicate a channel change should be considered, the
    Network Manager completes the following:

    a. Select a single channel based on the lowest energy in the
        :code:`Mgmt_NWK_Update_notify` message.
        This is the proposed new channel. If
        this new channel does not have an energy level below an acceptable
        threshold :code:`ZDNWKMGR_ACCEPTABLE_ENERGY_LEVEL`, then a channel change
        should not be considered.

    3. Prior to changing channels, the Network Manager stores the energy
    scan value as the last energy scan value and the failure rate from
    the existing channel as the last failure rate.

    4. The Network Manager prepares to broadcast (to the coordinator and all routers) a
    :code:`Mgmt_NWK_Update_req`, which will notify devices of the new channel.
    It increments the :code:`nwkUpdateId` parameter in the NIB and beacon payload,
    and includes it in the :code:`Mgmt_NWK_Update_req`. 
    After broadcasting, the Network Manager sets up a timer lasting
    :code:`ZDNWKMGR_UPDATE_REQUEST_TIMER` seconds.
    Another :code:`Mgmt_NWK_Update_req` to change channels will not
    be issued before this timer expires.

    5. Upon issue of a :code:`Mgmt_NWK_Update_req` with a change of channels,
    the local Network Manager sets a timer equal to the
    :code:`nwkNetworkBroadcastDeliveryTime` and switches channels upon
    expiration of this timer.

    Upon receipt of a :code:`Mgmt_NWK_Update_req` with a change of channels
    from the Network Manager, a device sets a timer equal to the
    :code:`nwkNetworkBroadcastDeliveryTime` and switches channels upon expiration
    of this timer. Each node stores the received :code:`nwkUpdateId` in the NIB and beacon payload,
    and also resets the total transmit and transmit failure counters.

    For devices with :code:`RxOnWhenIdle` equals :code:`FALSE`, any network channel
    change will not be received. On these devices or routers that have lost the
    network, an active scan is conducted on the :code:`channelList` in the NIB
    (i.e., :code:`apsChannelMask`) using the extended PAN ID (EPID) to find the
    network. If the extended PAN ID is found on different channels, the
    device selects the channel with the higher value in the :code:`nwkUpdateId`
    parameter. If the extended PAN ID is not found using the
    :code:`apsChannelMask` list, a scan is completed using all channels.

    Quick Reference
    ~~~~~~~~~~~~~~~

    +-------------------------------------------------------+---------------------------------------------+
    | Setting minimum transmissions attempted for Channel   | Set :code:`ZDNWKMGR_MIN_TRANSMISSIONS`      |
    | Interference detection                                | (in :code:`zd_nwk_mgr.h`)                   |
    +-------------------------------------------------------+---------------------------------------------+
    | Setting minimum transmit failure rate for Channel     | Set :code:`ZDNWKMGR_CI_TX_FAILURE`          |
    | Interference detection                                | (in :code:`zd_nwk_mgr.h`)                   |
    +-------------------------------------------------------+---------------------------------------------+
    | Setting minimum transmit failure rate for Channel     | Set :code:`ZDNWKMGR_CC_TX_FAILURE`          |
    | Change                                                | (in :code:`zd_nwk_mgr.h`)                   |
    +-------------------------------------------------------+---------------------------------------------+
    | Setting acceptable energy level threshold for Channel | Set :code:`ZDNWKMGR_ACCEPTABLE_ENERGY_LEVEL`|
    | Change                                                | (in :code:`zd_nwk_mgr.h`)                   |
    +-------------------------------------------------------+---------------------------------------------+
    | Setting APS channel timer for issuing Channel         | Set :code:`ZDNWKMGR_UPDATE_REQUEST_TIMER`   |
    | Changes                                               | (in :code:`zd_nwk_mgr.h`)                   |
    +-------------------------------------------------------+---------------------------------------------+

    PAN ID Conflict
    ---------------

    Since the 16-bit PAN ID is not a unique number there is a possibility of
    a PAN ID conflict in the local neighborhood. The Network Manager
    implements PAN ID conflict resolution.
    This section explains how the PAN ID of a network can be updated
    using the Network Report and Update commands.

    PAN ID Conflict Detection
    ~~~~~~~~~~~~~~~~~~~~~~~~~

    Any device that is operational on a network and receives a beacon in
    which the PAN ID of the beacon matches its own PAN ID but the EPID value
    contained in the beacon payload is either not present or not equal to
    :code:`extendedPanID`, is considered to have detected a PAN ID conflict.

    A node that has detected a PAN ID conflict sends a Network Report
    command of type PAN ID conflict to the designated Network Manager
    identified by the :code:`nwkManagerAddr` in the NIB. The Report Information
    field will contain a list of all the 16-bit PAN identifiers that are
    being used in the local neighborhood. The list is constructed from the
    results of an ACTIVE scan.

    PAN ID Conflict Resolution
    ~~~~~~~~~~~~~~~~~~~~~~~~~~

    The developer may choose what to do upon reception of a
    :code:`NWKREPORT_PANID_CONFLICT` inside the :code:`ZDNwkMgr_ProcessNetworkReport`
    function.  The decision to change PAN IDs should be based on factors
    outside the scope of the stack behavior and is directly related to the
    application performance.  Example code is provided to demonstrate the
    correct procedure for resolving a confirmed PAN identifier conflict.
    The following details its behavior as such.

    On receipt of the Network Report command, the Network Manager selects a
    new 16-bit PAN ID for the network. The new PAN ID is chosen at random,
    but a check is performed to ensure that the chosen PAN ID is not
    contained within the Report Information field of the network report
    command.

    Once a new PAN ID has been selected, the Network Manager first
    increments the NIB attribute :code:`nwkUpdateID` and then constructs a Network
    Update command of type PAN identifier update. The Update Information
    field is set to the value of the new PAN ID. After it sends out this
    command, the Network Manager starts a timer with a value equal to
    :code:`BCAST_DELIVERY_TIME` seconds (:code:`zglobals.h`). When the 
    timer expires, it changes its current PAN ID to the newly selected one.

    On receipt of a Network Update command of type PAN ID update from the
    Network Manager, a device (in the same network) starts a timer with a
    value equal to :code:`BroadcastDeliveryTime` seconds. When the timer
    expires, the device changes its current PAN ID to the value contained
    within the Update Information field. It also stores the new received
    :code:`nwkUpdateID` in the NIB and beacon payload.


    .. _z-stack-overview-green-power:

    Green Power
    ===========

    Introduction
    ------------

    The Green Power Specification enables the usage of energy-harvesting devices within a Zigbee network.
    Green Power Devices (GPD) have very limited energy budget, the standard association-based two-way communication
    model of Zigbee is not readily applicable. To enable GPD to communicate to Zigbee network, this
    specification defines a new frame format known as Green Power Device Frame (GPDF). This specification
    defines the required functionality on a Zigbee device to handle, process and tunnel the GPDF which are used
    to pair a GPD and perform control actions or report data.

    The specification defines the Green Power Stub which handles the data sent from GPD to be used by the
    Zigbee Stack, provides the commissioning procedures to pair green power devices with the Zigbee nodes
    to be controlled, and also defines the Green Power Cluster, used to hold GPD commissioning information
    and Zigbee commands used to tunnel GPDF payloads and to perform commissioning actions using Zigbee frames.

    From the application perspective the specification defines two types of devices: The Green Power Proxy
    devices, which only have to tunnel the received GPDF payloads; The Green Power Sink that manages the
    paired Green Power Devices on the Zigbee network, propagates the relevant information required for tunneling,
    and also able to process and execute Green Power commands tunneled by a Green Power Proxy or directly
    receiver from the Stub. Proxy Basic and Combo Basic are the Zigbee Green Power implementations for Proxy
    and Sink respectively that can be certified with the Proxy Basic implementation mandatory for Zigbee
    3.0 routing devices (coordinators or routers).

    A GPD has very limited power or relies on energy harvesting to function.
    It cannot perform the two way communication for establishing association to a Zigbee network.
    Instead, GPDs use Inter-PAN frames to commission itself into the network or to deliver commands.
    The commissioning methods and the type of commands supported by the GPD depend on its capabilities and resources. 
    The details of those commissioning methods and commands are beyond the scope of this document.

    The GP endpoint is implemented in the Zigbee reserved endpoint 242.

    .. _sec-green-power-data-frames:

    Green Power Data Frames (GPDF)
    ----------------------------------

    Most of the relevant information from a GPDF is contained in the NWK layer fields an no APS header
    and payload is required. GPDF format is defined in the Zigbee PRO Green Power Feature Specification,
    and an example of OTA GPDF is given below:

    .. code-block:: none

        "MAC Header":
            "Frame Control": 0x0801
                ···· ···· ···· ·001 = "Frame Type": [0x1] Data
                ···· ···· ···· 0··· = "Security Enabled": [0x0] No
                ···· ···· ···0 ···· = "Frame Pending": [0x0] No
                ···· ···· ··0· ···· = "Acknowledgement Request": [0x0] No
                ···· ···· ·0·· ···· = "Intra-PAN": [0x0] No
                ···· ··00 0··· ···· = "Reserved": 0x0
                ···· 10·· ···· ···· = "Destination Addr Mode": [0x2] "16-bit Short Address"
                ··00 ···· ···· ···· = "Reserved": 0x0
                00·· ···· ···· ···· = "Source Addr Mode": [0x0] No Address
        "Sequence Number": 1
            "Destination PAN ID": 0xFFFF
            "Destination Address": 0xFFFF
            "NWK Header":
                "Frame Control": 0x8C
                    ···· ··00 = "Frame Type": [0x0] Data Frame
                    ··00 11·· = "ZigBee Protocol Version": [0x3] Green Power
                    ·0·· ···· = "Auto Commissioning": [0x0] No
                    1··· ···· = "NWK Frame Control Extension": [0x1] Yes
                "Extended NWK Frame Control": 0x10
                    ···· ·000 = "Application ID": [0x0] ZGP
                    ···1 0··· = "Security Level": [0x0] No Security
                    ··0· ···· = "Security Key": [0x0] Shared Key
                    ·0·· ···· = "Rx After TX": [0x0] No
                    0··· ···· = "Direction": 0x0
                "ZGPD Source ID": 0x12345678
            "ZGP App Payload": 0x22
                "ZGPD Command ID": [0x22] Toggle

    +-----------------------+-----------------------------------------------+--------------------------------------------+
    | Name                  | Description                                   |  Values                                    |
    +-----------------------+-----------------------------------------------+--------------------------------------------+
    | GPDF_FRAME_DUPLICATES | (uint8) Application-specific.                 | | 0x00 - 0xFF (recommended to be low, more |
    |                       | Number of GPDF retries per packet.            |  retries = more power consumption)         |
    |                       |                                               |                                            |
    +-----------------------+-----------------------------------------------+--------------------------------------------+
    | GPD_CHANNEL           | IEEE channel, 11 - 26 (in Hex).               | | 0x0B - 0x1A                              |
    |                       |                                               |                                            |
    +-----------------------+-----------------------------------------------+--------------------------------------------+
    | SEQUENCE_NUMBER_CAP   | Defines if GPD will use incremental sequence  | | TRUE/FALSE                               |
    |                       | numbers or random sequence numbers.           |                                            |
    |                       |                                               |                                            |
    +-----------------------+-----------------------------------------------+--------------------------------------------+

    Zigbee Green Power Stub
    -----------------------

    The Green Power Stub implements the communication mechanism to process GPDFs and pass them to the
    Green Power EndPoint, 242. The Green Power Stub is divided in
    two sections; Common Green Power Stub (cGP) that is responsible for the GPDF packet formation and
    parsing, duplicate filtering, dropping of the GPDF based on addressing; Dedicated Green Power Stub
    (dGP) that performs just enough processing to pass application data frames to the cGP stub for
    transmission and to pass GPD commands from the cGP stub to the Green Power cluster on Green Power
    EndPoint upon receipt.

    Basic Green Power Network
    -----------------------------

    Then most basic Green Power network consists in three application entities:

    - Green Power Device (GPD).
    - Green Power Proxy (GP Proxy Basic).
    - Green Power Sink  (GP Combo Basic).

    .. _gp-GreenPowerNwk:
    .. figure:: resources/GreenPowerNwk.png
    :align: center

    Frames transmitted by a GPD are received by a Proxy Basic or Combo Basic (GPB or GCB). The frame
    received by a Proxy Basic is encapsulated as a standard ZCL frame and forwarded across the Zigbee network
    to a Combo Basic paired with the GPD. The frames received by the Combo Basic are processed internally
    by the proxy side and then passed to the sink.

    .. _sec-green-power-device:

    Green Power Device
    ------------------

    Green Power Devices can be put anywhere, especially in places where wiring is expensive or not possible.
    Zigbee Green Power enables a Zigbee Network to interact with smart devices that are battery-less or don't
    require maintenance. The Zigbee Network handless the complexity of routing the messages enabling this
    battery-less devices to stay connected and communicate.

    Green Power Devices are kept as simple as possible with regards to hardware, program implementation, and OTA frames. 
    This simplicity aims to reduce power consumption, 
    which further enables long battery life and introduces the possiblity of using energy harvesting as a power source.
    The Green Power Specification relies on Zigbee devices with routing capabilities
    to deal with the complexity of frame deliveries, network security, and maintenance;
    a GPD just broadcasts GPDFs, unaware of the tunneling and processing of GPDFs performed by the proxies and sinks.

    The GPD's Device ID (:code:`DEVICE_ID`, referenced as the *Green Power Device Type*) 
    determines its application functionality as defined by the Green Power Specification.  Device ID type
    (:code:`GPD_APP_ID`) can determine whether it is a configurable value (:code:`GPD_ID`) or uses
    the device's extended IEEE address (:code:`ApiMac_extAddr`). 

    +------------+-----------------------------------------------+----------------------------------+
    | Name       | Description                                   |  Values                          |
    +------------+-----------------------------------------------+----------------------------------+
    | DEVICE_ID  | (uint8) Green Power Device ID which indicates | | 0x00 - 0xFF, refer to GPD spec |
    |            | the device application functionality.         |                                  |
    |            |                                               |                                  |
    +------------+-----------------------------------------------+----------------------------------+
    | GPD_APP_ID | Unique identifier of the GPD, either the      | | 0b00 GPD_APP_TYPE_SRC_ID       |
    |            | 4-byte SrcID or the IEEE Addr.                | | 0b10 GPD_APP_TYPE_IEEE_ID      |
    |            |                                               |                                  |
    +------------+-----------------------------------------------+----------------------------------+
    | GPD_ID     | SrcID if GPD_APP_ID = 0b00                    | | 0x00000000 - 0xFFFFFFFF        |
    |            |                                               |                                  |
    +------------+-----------------------------------------------+----------------------------------+

    .. note:: All Green Power Device settings are configurable inside the project's .syscfg file

    Green Power Basic Proxy
    -----------------------

    As a requirement for Zigbee 3.0 certification, all Zigbee routing devices
    (coordinators and routers) must support the Green Power Basic proxy, which
    is an application that can relay commands from a GPD to a GPS device.

    The Basic proxy requires the implementation of GP stub and GP cluster.
    The GP stub handles the Inter-PAN commands and passes those to the GP
    endpoint application. It also sends GP data frames back to the GPD for
    certain commissioning methods.
    The GP stub is defined in such a way that different applications can sit on top of it, such as a Sink Device.
    For further details on Sink Device implementation refer to [4].

    When a GPB receives a GPDF it looks for an entry for the GPD in the *Proxy Table*. If the entry is
    found a ZCL Green Power Notification command is generated for all paired sinks. The addressing for
    the Green Power Notifications is taken from the *Proxy Table* according to the pairing information
    with each sink to the GPD. If no entry for the GPD is found, the GPDF is discarded.

    .. uml::
        :caption: GPDF tunneling
        :align: center

        @startuml
        participant "GPD"
        participant "GPB"
        participant "GCB"

        "GPD"->"GPB": GPDF
        note over GPB
                Proxy looks for
                GPD entry on
                proxy table
        end note
        "GPB"->"GPB": gppTunnelingDelay
        "GPB"->"GCB": ZCL GP Notification
        "GCB"->"GCB": The sink module processes the notification
        note over GCB
            Green Power
            command
                executed
        end note
        @enduml

    Since the GP basic proxy is an application to relay the commands to a
    Sink device, no functionality needs to be handled by the application
    (e.g. light, switch, etc.) that's running the GP basic proxy.
    The only interface between them is the following:

    -  :code:`gp_RegisterGPChangeChannelReqCB()`: Register a callback that requests
    for permission to switch the operational channel to
    the GPD’s channel to perform commissioning.
    The callback registered may return :code:`FALSE` to not allow the channel change
    if an application operation cannot be interrupted.
    Permission is also requested from the BDB module.
    If the callback returns :code:`TRUE` or no callback is registered, then the GP basic
    proxy application will handle the change of channels.
    The channel change lasts for at most :code:`gpBirectionalCommissioningChangeChannelTimeout` 
    (5 seconds, :code:`gp_interface.h`).

    Green Power Sink
    ----------------

    The GP Sink is a service that the device application can register for,
    which allows the device to receive and process GP Data Frames.
    A callback list is provided for the device application to handle GP notification commands.

    .. code-block:: c

        typedef struct
        {
        #ifdef ZCL_IDENTIFY
        GPDFCB_GP_identify_t                pfnGpdfIdentifyCmd;
        #endif
        #ifdef ZCL_SCENES
        GPDFCB_GP_RecallScene_t             pfnGpdfRecallSceneCmd;
        GPDFCB_GP_StoreScene_t              pfnGpdfStoreSceneCmd;
        #endif
        #ifdef ZCL_ON_OFF
        GPDFCB_GP_Off_t                     pfnGpdfOffCmd;
        GPDFCB_GP_On_t                      pfnGpdfOnCmd;
        GPDFCB_GP_Toggle_t                  pfnGpdfToggleCmd;
        #endif
        #ifdef ZCL_LEVEL_CTRL
        GPDFCB_GP_LevelControlStop_t        pfnGpdfLevelControlStopCmd;
        GPDFCB_GP_MoveUp_t                  pfnGpdfMoveUpCmd;
        GPDFCB_GP_MoveDown_t                pfnGpdfMoveDownCmd;
        GPDFCB_GP_StepUp_t                  pfnGpdfStepUpCmd;
        GPDFCB_GP_StepDown_t                pfnGpdfStepDownCmd;
        GPDFCB_GP_MoveUpWithOnOff_t         pfnGpdfMoveUpWithOnOffCmd;
        GPDFCB_GP_MoveDownWithOnOff_t       pfnGpdfMoveDownWithOnOffCmd;
        GPDFCB_GP_StepUpWithOnOff_t         pfnGpdfStepUpWithOnOffCmd;
        GPDFCB_GP_StepDownWithOnOff_t       pfnGpdfStepDownWithOnOffCmd;
        #endif
        GPDFCB_GP_MoveHueStop_t             pfnGpdfMoveHueStopCmd;
        GPDFCB_GP_MoveHueUp_t               pfnGpdfMoveHueUpCmd;
        GPDFCB_GP_MoveHueDown_t             pfnGpdfMoveHueDownCmd;
        GPDFCB_GP_StepHueUp_t               pfnGpdfStepHueUpCmd;
        GPDFCB_GP_StepHueDown_t             pfnGpdfStepHueDownCmd;
        GPDFCB_GP_MoveSaturationStop_t      pfnGpdfMoveSaturationStopCmd;
        GPDFCB_GP_MoveSaturationUp_t        pfnGpdfMoveSaturationUpCmd;
        GPDFCB_GP_MoveSaturationDown_t      pfnGpdfMoveSaturationDownCmd;
        GPDFCB_GP_StepSaturationUp_t        pfnGpdfStepSaturationUpCmd;
        GPDFCB_GP_StepSaturationDown_t      pfnGpdfStepSaturationDownCmd;
        GPDFCB_GP_MoveColor_t               pfnGpdfMoveColorCmd;
        GPDFCB_GP_StepColor_t               pfnGpdfStepColorCmd;
        #ifdef ZCL_DOORLOCK
        GPDFCB_GP_LockDoor_t                pfnGpdfLockDoorCmd;
        GPDFCB_GP_UnlockDoor_t              pfnGpdfUnlockDoorCmd;
        #endif
        GPDFCB_GP_AttributeReporting_t      pfnGpdfAttributeReportingCmd;
        GPDFCB_GP_MfrSpecificReporting_t    pfnGpdfMfrSpecificReportingCmd;
        GPDFCB_GP_MultiClusterReporting_t   pfnGpdfMultiClusterReportingCmd;
        GPDFCB_GP_MfrSpecificMultiReporting_t pfnGpdfMfrSpecificMultiReportingCmd;
        GPDFCB_GP_RequestAttributes_t       pfnGpdfRequestAttributesCmd;
        GPDFCB_GP_ReadAttributeRsp_t        pfnGpdfReadAttributeRspCmd;
        GPDFCB_GP_zclTunneling_t            pfnGpdfzclTunnelingCmd;
        } GpSink_AppCallbacks_t;

    :code:`zclGp_RegisterCBForGPDCommand()` registers the callback list with
    the user defined callback functions. When a notification for a registered
    command functions arrives, the Sink will relay the frame to the application
    callback.

    The GCB maintains the proxy functionality. Additionally, it also implements the sink functionality.
    This means that when a GPD is in range and there is an entry for it in the GCB's sink table, GPDFs from this GPD are processed
    directly by the GCB without need of an additional proxy. 
    Due to proxy functionality, the GCB will also generate ZCL Green Power notifications 
    in case other sinks have pairings in their proxy table.

    .. uml::
        :caption: Direct GPDF
        :align: center

        @startuml
        participant "GPD"
        participant "GCB"

        "GPD"->"GCB": GPDF
        "GCB"->"GCB": The proxy processes the \nGPDF and generates a \nnotification for the sink
        note over GCB
            Green Power
            command
            executed
        end note
        @enduml

    .. _sec-green-power-commissioning:

    Commissioning a Green Power Device
    ----------------------------------

    A GPD must be commissioned to a Zigbee Device with the Combo Basic implementation to have its GPDFs processed and executed. 
    It is left to the implementers of sink when to update pairings in the Sink Table and when to enter or exit commissioning mode.

    Methods of commissioning the GPD include proximity and multi-hop commissioning, detailed below.

    *Proximity commissioning*: This procedure involves a GPD within radio range of a Combo Basic.

    1. Combo Basic is already operating in a Zigbee network.
    2. A user action on Combo Basic puts the device in commissioning mode.
    3. A user action on GPD makes it send a commissioning frame.
    4. Combo Basic creates an entry on the sink table for the GPD.
    5. Combo Basic sends a Pairing command for the Proxy Basic(s).
    6. Now the Combo Basic will execute a command frame either received directly from the GPD or tunneled by a Proxy Basic.

    *Multi-hop commissioning*: This procedure involves a GPD that can be heard directly by a Proxy Basic that will
    tunnel the frames to a Combo Basic.

    1. Combo Basic and Proxy Basic are already operating in a Zigbee network.
    2. A user action on Combo Basic puts the device in commissioning mode.
    3. Combo Basic sends a ZCL message to Proxy Basic to put the device in commissioning mode.
    4. A user action on GPD makes it send a commissioning frame.
    5. Proxy Basic tunnels the commissioning frame within a ZCL frame.
    6. Combo Basic creates an entry on the sink table for the GPD.
    7. Combo Basic sends a Pairing command for the Proxy Basic.
    8. Now the Combo Basic will execute a command frame either received directly from the GPD or tunneled by a Proxy Basic.

    +--------------------+-----------------------------------------------+---------------+
    | Name               | Description                                   |  Values       |
    +--------------------+-----------------------------------------------+---------------+
    | GPD_CHANNEL        | IEEE channel, 11 - 26 (in Hex).               | | 0x0B - 0x1A |
    |                    |                                               |               |
    +--------------------+-----------------------------------------------+---------------+
    | AUTO_COMMISSIONING | Defines whether or not the device will start  | | TRUE/FALSE  |
    |                    | commissioning procedure using application     |               |
    |                    | GPDF. This is for devices with limited        |               |
    |                    | resources not capable of sending              |               |
    |                    | commissioning frames.                         |               |
    |                    |                                               |               |
    +--------------------+-----------------------------------------------+---------------+
    | RX_AFTER_TX        | RxOnCapability commissioning option.          | | TRUE/FALSE  |
    |                    | Defines whether or not GPD will turn RX       |               |
    |                    | on after TXing a frame, i.e. whether or       |               |
    |                    | not GPD is expecting a response.              |               |
    |                    |                                               |               |
    +--------------------+-----------------------------------------------+---------------+

    .. _sec-green-power-security:

    Green Power Security
    --------------------

    The Green Power Specification defines four levels of security for GPDF protection (summarized in table below) that is
    applied to the network layer payload. Some GPD implementations are capable of exchanging the key that will be used for
    frame protection while others make use of a preconfigured key. A freshness authentication for GPDF retransmission
    is performed by proxies and sinks for all security levels. Security authentication is done if security level 0b10 or
    0b11 is supported. The Zigbee PRO Green Power Feature Specification has more detailed information.

    Values for Green Power Security Level

    +----------------------------+-----------------------------------------------+------------------------------------------------+
    | Name                       | Description                                   |  Values                                        |
    +----------------------------+-----------------------------------------------+------------------------------------------------+
    | EXT_OPT_KEY_TYPE           | Specifies the type of key which GPDFs are     | | 0b000 KEY_TYPE_NO_KEY                        |
    |                            | secured with.                                 | | 0b001 KEY_TYPE_ZIGBEE_NWK_KEY                |
    |                            |                                               | | 0b010 KEY_TYPE_GPD_GROUP_KEY                 |
    |                            |                                               | | 0b011 KEY_TYPE_NWK_KEY_DERIVED_GPD_GROUP_KEY |
    |                            |                                               | | 0b100 KEY_TYPE_OUT_BOX_GPD_KEY               |
    |                            |                                               | | 0b111 KEY_TYPE_DERIVED_INDIVIDUAL_GPD_KEY    |
    |                            |                                               |                                                |
    +----------------------------+-----------------------------------------------+------------------------------------------------+
    | GP_SECURITY_KEY            | The 128-bit security key used to encrypt      | | 8 bytes from all 0x00 to all 0xFF            |
    |                            | Green Power Data Frames.                      |                                                |
    |                            |                                               |                                                |
    +----------------------------+-----------------------------------------------+------------------------------------------------+
    | GP_SECURITY_LEVEL          | Defines the security level for GPDF payload.  | | 0b00 GP_SECURITY_LVL_NO_SEC                  |
    |                            |                                               | | 0b01 Reserved                                |
    |                            |                                               | | 0b10 GP_SECURITY_LVL_4FC_4MIC                |
    |                            |                                               | | 0b11 GP_SECURITY_LVL_4FC_4MIC_ENCRYPT        |
    |                            |                                               |                                                |
    +----------------------------+-----------------------------------------------+------------------------------------------------+

    Inter-PAN Transmission
    ======================

    Overview
    --------

    Inter-PAN transmission enables Zigbee devices to perform limited,
    insecure, and possibly anonymous exchange of information with devices in
    their local neighborhood without having to form or join the same Zigbee
    network.

    The Inter-PAN feature is implemented by the Stub APS layer, which can be
    included in a project by defining the :code:`INTER_PAN` compile option and
    including :code:`stub_aps.c` and :code:`stub_aps.h` files in the project.

    Data Exchange
    -------------

    Inter-PAN data exchanges are handled by the Stub APS layer, which is
    accessible through INTERP-SAP, parallel to the normal APSDE-SAP:

    -  The :code:`INTERP_DataReq()` and :code:`APSDE_DataReq()` are invoked from
    :code:`AF_DataRequest()` to send Inter-PAN and Intra-PAN messages
    respectively.

    -  The :code:`INTERP_DataIndication()` invokes :code:`APSDE_DataIndication()`
    to indicate the transfer of Inter-PAN data to the local application
    layer entity. The application then receives Inter-PAN data as a
    normal incoming data message (:code:`APS_INCOMING_MSG`) from the APS
    sub-layer with the source address belonging to an external PAN
    (verifiable by :code:`StubAPS_InterPan()` API) .

    -  The :code:`INTERP_DataConfirm()` invokes :code:`afDataConfirm()` to send an
    Inter-PAN data confirm back to the application. The application
    receives a normal data confirm (:code:`AF_DATA_CONFIRM_CMD`) from the AF
    sub-layer.

    The Stub APS layer also provides interfaces to switch channel for
    Inter-PAN communication and check for Inter-PAN messages. Please refer
    to the |ZSTACK_API| for detailed description of the
    Inter-PAN APIs.

    The :code:`StubAPS_InterPan()` API is used to check for Inter-PAN messages. A
    message is considered as an Inter-PAN message if it meets one the
    following criteria:

    -  The current communication channel is different than the device’s NIB
    channel.

    -  The current communication channel is the same as the device’s NIB
    channel but the message is destined for a PAN different than the
    device’s NIB PAN ID.

    -  The current communication channel is the same as the device’s NIB
    channel and the message is destined for the same PAN as device’s
    NIB PAN ID but the destination application endpoint is an
    Inter-PAN endpoint (0xFE). This case is true for an Inter-PAN
    response message that’s being sent back to a requestor.

    A typical usage scenario for Inter-PAN communication is as follows. The
    initiator device:

    1. Calls :code:`StubAPS_AppRegister()` API to register itself with the Stub APS
    layer.

    2. Calls :code:`StubAPS_SetInterPanChannel()` API to switch its communication
    channel to the channel in use by the remote device.

    3. Specifies the destination PAN ID and address for the Inter-PAN
    message about to be transmitted.

    4. Calls :code:`AF_DataRequest()` API to send the message to the remote device
    through Inter-PAN channel.

    5. Receives back (if required) a message from the remote device that
    implements the Stub APS layer and is able to respond.

    6. Calls :code:`StubAPS_SetIntraPanChannel()` API to switch its communication
    channel back to its original channel.  This API should only be used for
    devices which have already joined or formed a Zigbee network and thus been
    assigned a logical channel.  It is also important that this API not be
    used until after receiving :code:`zstackmsg_CmdIDs_AF_DATA_CONFIRM_IND` from
    the transmitted Inter-PAN message.

    Quick Reference
    ~~~~~~~~~~~~~~~

    +--------------------------------------------+----------------------------------------------------------------------+
    | Setup application as InterPAN application. | Call :code:`StubAPS_AppRegister(app_endpoint)`                       |
    +--------------------------------------------+----------------------------------------------------------------------+
    | Set InterPAN channel.                      | Call :code:`StubAPS_SetInterPanChannel(channel)`                     |
    +--------------------------------------------+----------------------------------------------------------------------+
    | Send InterPAN Message.                     | Call :code:`AF_DataRequest()` with:                                  |
    |                                            |                                                                      |
    |                                            | -  :code:`dstPanID` different from                                   |
    |                                            |    :code:`_NIB.nwkPanId`                                             |
    |                                            |                                                                      |
    |                                            | -  :code:`dst address endpoint == STUBAPS_INTER_PAN_EP`              |
    |                                            |                                                                      |
    +--------------------------------------------+----------------------------------------------------------------------+
    | Receive an InterPAN message.               | Receive an :code:`AF_INCOMING_MSG_CMD`                               |
    |                                            | message with an incoming :code:`DstEndPoint == STUBAPS_INTER_PAN_EP` |
    |                                            |                                                                      |
    +--------------------------------------------+----------------------------------------------------------------------+
    | End the InterPAN session by putting back   | Call :code:`StubAPS_SetIntraPanChannel()`                            |
    | the IntraPAN channel.                      |                                                                      |
    +--------------------------------------------+----------------------------------------------------------------------+

    ZMAC LQI Adjustment
    ===================

    Overview
    --------

    The IEEE 802.15.4 specification provides some general statements on the
    subject of LQI. From section 6.7.8: "The minimum and maximum LQI values
    (0x00 and 0xFF) should be associated with the lowest and highest IEEE
    802.15.4 signals detectable by the receiver, and LQI values should be
    uniformly distributed between these two limits." From section E.2.3:
    "The LQI (see 6.7.8) measures the received energy and/or SNR for each
    received packet. When energy level and SNR information are combined,
    they can indicate whether a corrupt packet resulted from low signal
    strength or from high signal strength plus interference."

    The TI MAC computes an 8-bit “link quality index” (LQI) for each
    received packet from the 2.4 GHz radio. The LQI is computed from the raw
    “received signal strength index” (RSSI) by linearly scaling it between
    the minimum and maximum defined RF power levels for the radio. This
    provides an LQI value that is based entirely on the strength of the
    received signal. This can be misleading in the case of a narrowband
    interferer that is within the channel bandwidth – the RSSI may be
    increased even though the true link quality decreases.

    The TI radios also provide a “correlation value” that is a measure of
    the received frame quality. Although not considered by the TI MAC in LQI
    calculation, the frame correlation is passed to the ZMAC layer (along
    with LQI and RSSI) in MCPS data confirm and data indication callbacks.
    The :code:`ZMacLqiAdjust()` function in :code:`zmac_cb.c` provides 
    capability to adjust the default TI MAC value of LQI by taking the 
    correlation into account.

    LQI Adjustment Modes
    --------------------

    LQI adjustment functionality for received frames processed in :code:`zmac_cb.c`
    has three defined modes of operation - :code:`OFF`, :code:`MODE1`, and :code:`MODE2`. To
    maintain compatibility with previous versions of |STACK| which do not
    provide for LQI adjustment, this feature defaults to :code:`OFF`, as defined
    by an initializer (:code:`lqiAdjMode = LQI_ADJ_OFF`) in :code:`zmac_cb.c` –
    developers can select a different default state by changing this
    statement.

    :code:`MODE1` provides a simple algorithm to use the packet correlation value
    (related to SNR) to scale incoming LQI value (related to signal
    strength) to 'de-rate' noisy packets. The incoming LQI value is linearly
    scaled with a "correlation percentage" that is computed from the raw
    correlation value between theoretical minimum/maximum values
    (:code:`LQI_CORR_MIN` and :code:`LQI_CORR_MAX` are defined in :code:`ZMAC.h`).

    :code:`MODE2` provides a “stub” for developers to implement their own
    proprietary algorithm. Code can be added after the
    :code:`else if (lqiAdjMode == LQI_ADJ_MODE2)` statement in :code:`ZMacLqiAdjust()`.

    Using LQI Adjustment
    --------------------

    There are two ways to enable the LQI adjustment functionality:

    (1) Alter the initialization of the :code:`lqiAdjMode` variable as described in
        the previous section

    (2) Call the function :code:`ZMacLqiAdjustMode()` from somewhere within the
        |STACK| application, most likely from the application’s task
        initialization function. See the |ZSTACK_API| on details
        of this function.

    The :code:`ZMacLqiAdjustMode()` function can be used to change the LQI
    adjustment mode as needed by the application. For example, a developer
    might want to evaluate device/network operation using a proprietary
    :code:`MODE2` compared to the default :code:`MODE1` or :code:`OFF`.

    Tuning of :code:`MODE1` operation can be achieved by altering the values of
    :code:`LQI_CORR_MIN` and/or :code:`LQI_CORR_MAX`. Alternate values for these
    parameters can be provided as compiler
    directives in the IDE project file or in one of Z-Stack’s configuration files. Refer to
    the radio’s data sheet for information on the normal minimum/maximum correlation values.
