Green Power Application Overview
=======================================

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

A Green Power Device (GPD) is a special type of Zigbee device different from the three logical devices defined in Zigbee PRO: 
*Coordinator*, *Router* or *End Device*.  GPDs are designed for applications where the end product has a very strict 
energy budget, such as an energy-harvesting device or batteryless devices. GPDs follow their own Zigbee Green Power specification which 
defines the possible capabilities of a given GPD implementation, such as security level, commissioning procedures and supported 
commands per device definition.

As GPDs are the most restricted device in terms of functionality, these devices are not part of 
the Zigbee network unless they are commissioned to a Green Power Sink (GPS) device directly or through a Green Power Proxy 
(GPP). Although GPS is a specific application function to be added, the GPP feature is automatically applied to all routing nodes 
(Zigbee coordinators and routers) as required to meet Zigbee product compliancy (see :ref:`sec-product-certification`). If the device to 
which a GPD is commissioned to is not present, then the GPD must be recommissioned, as it does not have a means to keep communication 
with any other device.

Once the GPD is commissioned it can send Green Power Data Frames (GPDF) which 
are converted by the GPP into Green Power Notifications (ZCL frames) that can travel through the Zigbee network until it reaches 
its GPS destination to be processed by the application. For further details on GPDs and their interactions with the network, 
please refer to :ref:`z-stack-overview-green-power`.


.. _sec-gpd-general-application-architecture:

General Application Architecture
--------------------------------

This section describes how a Green Power Device application task is 
structured in more detail.  Refer to the :ref:`chap-example-applications` to 
determine which |STACK| examples support specific Green Power functionality 
(GPD and GPS). 

.. _sec-gpd-configuration:

Green Power Device Configuration
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Configuration definitions are used at build time and determine the behavior of 
the device at runtime. Thus, to change the Green Power Device behavior, it is 
ecessary to modify the SysConfig settings, the descriptions of which are covered 
in :ref:`z-stack-overview-green-power`.  An example of creating a GPD switch is 
given below (found in :code:`Debug/syscfg/ti_zigbee_config.h` of the 
:code:`gpd_switch` project after building).

.. code-block:: c

    /******************************************************************************
    * CONFIGURATION
    */

    #ifndef CHANNEL_LIST
    #define CHANNEL_LIST            {17}
    #endif



    #ifndef GPD_APP_ID_TYPE
    #define GPD_APP_ID_TYPE         0
    #endif

    #ifndef GPD_SRC_ID
    #define GPD_SRC_ID              0xabacadac
    #endif

    #ifndef SECURITY_LEVEL
    #define SECURITY_LEVEL          3
    #endif

    #ifndef SECURITY_KEY_TYPE
    #define SECURITY_KEY_TYPE       4
    #endif

    #ifndef SECURITY_KEY
    #define SECURITY_KEY            {0xCF,0xCE,0xCD,0xCC,0xCB,0xCA,0xC9,0xC8,0xC7,0xC6,0xC5,0xC4,0xC3,0xC2,0xC1,0xC0}
    #endif

    #ifndef GPDF_REPETITIONS
    #define GPDF_REPETITIONS        3
    #endif

    #ifndef UNIDIR_DEVICE
    #define UNIDIR_DEVICE           ZB_FALSE
    #endif

    #ifndef BATTERYLESS_DEVICE
    #define BATTERYLESS_DEVICE      ZB_TRUE
    #endif

Additional definitions are located from the *Project Properties* |rarr| *Build* 
|rarr| *ARM Compiler* |rarr| *Predefined Symbols* but should not be changed.

.. _sec-gpd-application:

Application
^^^^^^^^^^^

The application code is minimal to reduce power consumption on device start-up 
(from :code:`gpd_switch.c`):

.. code-block:: c

    MAIN()
    {
      /* Variable where a mask of pressed buttons will be stored to */
      zb_uint32_t button_mask = 0;
      zb_uint32_t button_id = 0;
      zb_uint_t comm_steps = 0;

      ARGV_UNUSED;

      /* Platform-specific initialization */
      zgpd_platform_init(ARGC_ARGV);

      TRACE_INIT("zgpd_bidir_battery_onoff");

      /* ZPGD stack init */
      zgpd_app_init(g_zgpd_encryption_key, &g_device_config);

    #if ( UNIDIR_DEVICE == ZB_FALSE )

    #if ( BATTERYLESS_DEVICE == ZB_TRUE )
      zgpd_bidir_batteryless_mode();
    #else
      zgpd_bidir_battery_mode();
    #endif // BATTERYLESS_DEVICE == ZB_TRUE

    #elif ( BATTERYLESS_DEVICE == ZB_FALSE )
        // Enable button decounce if unidirectional and not a batteryless device
        zgpd_button_enable_debounce();
    #endif // UNIDIR_DEVICE == ZB_FALSE

      /* Inform platform layer about buttons number */
      zgpd_set_buttons_max_num(BUTTONS_NUM);

    #if (BATTERYLESS_DEVICE == ZB_FALSE)
      while (1)
    #endif // BATTERYLESS_DEVICE == ZB_FALSE
      {
        /* Get mask of buttons pressed at power ON time - if multiple are pressed
          simultaneously, only the higher index is considered */
        zgpd_wait_for_button();
        button_mask = zgpd_test_get_button_mask();
        button_id = 31 - MAGIC_CLZ(button_mask);

        switch (button_id)
        {
        case BUTTON_COMMISSIONING:

    #if ( UNIDIR_DEVICE == ZB_TRUE )
          zgpd_unidir_commissioning_step(&g_device_config, &g_tx_cfg);
    #else

    #if ( BATTERYLESS_DEVICE == ZB_TRUE )
          if (!zgpd_bidir_is_commissionned())
          {
            /* In bidir batteryless we can do only one commissioning iteration a time, then die */
            zgpd_bidir_commissioning_step(&g_device_config, &g_tx_cfg);
          }
    #else // Battery Bidirectional Device
          /* Commissioning button pressed when alredy commissioned - let's decommission this device */
          if (zgpd_bidir_is_commissionned())
          {
            zgpd_bidir_decommission(&g_device_config, &g_tx_cfg);
            break;
          }

          /** [bidir_step] */
          /* In contrast to batteryless bidir commissioning, here we can do multiple
          * iterations until commissioning complete. */
          while (!zgpd_bidir_is_commissionned())
          {
            zgpd_bidir_commissioning_step(&g_device_config, &g_tx_cfg);

            /* If can't commission, do not loop there forever */
            comm_steps++;
            if (comm_steps > COMM_STEPS_LIMIT)
            {
              break;
            }
          }
          comm_steps = 0;
          /** [bidir_step] */

          if (!zgpd_bidir_is_commissionned())
          {
            /* If could not commission, go to deep sleep to save the battery */
            continue;
          }
    #endif // BATTERYLESS_DEVICE == ZB_TRUE
    #endif // UNIDIR_DEVICE == ZB_TRUE
          break;

        case BUTTON_ON:
          /* Button 1 pressed - send ON */
          ZGPD_CMD_ON(&g_device_config, &g_tx_cfg);
          /** [button2] */
          break;

        case BUTTON_TOGGLE:
          /* Button 2 pressed - send TOGGLE */
          ZGPD_CMD_TOGGLE(&g_device_config, &g_tx_cfg);
          break;

        case BUTTON_OFF:
          /* Button 3 pressed - send OFF */
          ZGPD_CMD_OFF(&g_device_config, &g_tx_cfg);
          break;

        default:
          break;
        }
    #if ( BATTERYLESS_DEVICE == ZB_TRUE )
        osif_deep_sleep();
    #endif // BATTERYLESS_DEVICE == ZB_TRUE
      }
    }

Mode and commissioning functions used, along with button operations, are 
dependent on the :code:`BATTERYLESS_DEVICE` and :code:`UNIDIR_DEVICE` pre-definitions.

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

Send Green Power Data Frames
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

API prototypes to send Green Power Data Frames (GPDF) is provided 
in :code:`zb_command.h`. The generic function :code:`zb_zgpd_payloadless_cmd()` 
sends a frame formated for the Green Power Device configuration automatically by 
providing a :code:`zgpd_tx_cfg_t` struct with the formatted :code:`zgpd_device_config_t`
device configuration.

Setting Up the Network with GPD and GPS
---------------------------------------

To set up a network with a Green Power Device (GPD) and a Green Power Sink (GPS), you will need 2-3 devices:

  1. Green Power Device (:code:`gpd_switch` or :code:`gpd_attr_reporting`)
  #. Green Power Sink
  #. Optional: Green Power Proxy (any other Zigbee 3.0 routing device)

Select Network Channel
^^^^^^^^^^^^^^^^^^^^^^

First, determine which channel you would like to use for your test. On the Green 
Power Sink (and Green Power Proxy, if applicable), configure the channel mask 
accordingly (see :ref:`z-stack-overview-configuring-channel`). Select the same 
channel for the Green Power Device (see :ref:`sysconfig-zigbee-radio-configuration`).

Create and Open the Network on the GPS
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Next, create a network with your coordinator.

Join the GPP Device
^^^^^^^^^^^^^^^^^^^

If you would prefer a Green Power Proxy (GPP) to route GP Data Frames, it must 
be joined to the network formed by the coordinator. 

    .. note:: This step is entirely optional as the GPD can be directly commissioned to the GPS coordinator

Enable Commissioning on the GPS
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Next, enable GPS Commissioning on the ZC GP Sink.

Commission the GPD into the Network
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Lastly, commission a GPD like the :code:`gpd_switch` into the network by following the instructions in the **Commissioning the device Into the network** 
section of this readme:

-  :docs_root:`Green Power Switch Readme  <../examples/rtos/LP_EM_CC2340R5/zigbee/gpd_switch/README.html>`

Example Sniffer Capture of Green Power Traffic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Here is an annotated Zigbee sniffer log of the expected behavior following the instructions above:

.. figure:: resources/green-power-network-example.png
    :align: center
