This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2530: How to achieve periodic reporting of battery voltage value using Power Configuration Cluster

Part Number: CC2530
Other Parts Discussed in Thread: Z-STACK

Is there a way i can configure an end device to periodically notify coordinator about the battery voltage measure at its end using Power Configuration Cluster?

I tried adding "

bdb_RepAddAttrCfgRecordDefaultToList(TEMPERATURESENSOR_ENDPOINT, ZCL_CLUSTER_ID_GEN_POWER_CFG, ATTRID_POWER_CFG_BATTERY_PERCENTAGE_REMAINING, 0, 10, reportableChange);" to my end device code but from log i see it doesn't work as expected.

My cluster and attribute list as follows

const cId_t zclTemperatureSensor_InClusterList[ZCLTEMPERATURESENSOR_MAX_INCLUSTERS] =

{

ZCL_CLUSTER_ID_GEN_BASIC,

ZCL_CLUSTER_ID_GEN_POWER_CFG,

ZCL_CLUSTER_ID_GEN_IDENTIFY,

ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT

};

// *** Power Configuration Attriubtes ***

{

ZCL_CLUSTER_ID_GEN_POWER_CFG,

{ // Attribute record

ATTRID_POWER_CFG_BATTERY_PERCENTAGE_REMAINING,

ZCL_DATATYPE_UINT8,

ACCESS_CONTROL_READ | ACCESS_REPORTABLE,

(void *)&zclTemperatureSensor_BattRemaining

}

},

  • Hi,

    BDB reporting will only work if an appropriate bind is created in your Zigbee network, i.e. between the server and client side of the Power Cfg cluster. In this case, your end device supports the server side (output) of the cluster, but another device in your network (i.e. ZC) must support the client side (input) of the cluster, and you must create a bind between these two devices (from server to client) using either BDB Finding & Binding, manual device binding via ZDP_BindReq, or another binding method. Once this bind exists, BDB reporting will automatically start.

    If you have already done this and it is still not working, please post of your device successfully joining the network, creating the bind, and then not starting the attribute reporting automatically, and we can go from there.
  • Can you do a sniffer log of your device successfully joining the network, creating the bind, and then not starting the attribute reporting automatically and attach it?
  • Hi,

    Thank you for your response. Yes, i have another device (ZC) on my network that support the client side of the cluster. See below the cluster list configured at the ZC side.

    const cId_t zclSampleThermostat_OutClusterList[ZCLSAMPLETHERMOSTAT_MAX_OUTCLUSTERS] =

    {

     ZCL_CLUSTER_ID_GEN_IDENTIFY,

     ZCL_CLUSTER_ID_GEN_POWER_CFG,

     ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT

    };

    Also as you mentioned i have bind these two devices using BDB finding and binding method (see the attached sniffer log). To highlight  power configuration cluster doesn't report the attribute i have set the MS Temperature Measurement cluster to report measured value to ZC and it works. 

    No Periodic Attr Reporting.cubx.zip

    NOTE:- i'm using temperature sensor and thermostat as the base application for my experiment.

  • Please refer the attached sniffer log in my response to Jason's message.
  • There is no binding of power configuration cluster in your sniffer log.
  • Doesn't the BDB Finding & Binding automatically does the binding? How come MS Temperature Measurement cluster able to report data to ZC. I did not do a manual end device binding for MS Temperature Measurement cluster.
  • There is no temperature cluster binding in your sniffer log too. Do you start finding and binding process from both ZC and ZED after ZED joins ZC?
  • I use the sample temperature sensor and thermostat application. From the sample code i observe when user presses the commissioning button on ZC it calls bdb_StartCommissioning(uiSelectedBdbComissioningModes) in which uiSelectedBdbComissioningModes is set to #define DEFAULT_COMISSIONING_MODE (BDB_COMMISSIONING_MODE_NWK_STEERING | BDB_COMMISSIONING_MODE_NWK_FORMATION | BDB_COMMISSIONING_MODE_FINDING_BINDING) i assume it is the same for ZED.

    My device start-up procedure is as follows: Start Coordinator first and run commissioning process from menu options. After 5 seconds i turn on ZED and repeat commissioning process like done on ZC.

    Correct me if i'm doing any thing wrong. Also enlighten me on the necessary binding process to be done between ZC and ZED in order to bind devices and exchange data between them.
  • Hi YiKai Chen,

    Do you have any inputs for my query listed above?
  • Hi,

    BDB Finding & Binding only creates binds for clusters which are Application type clusters. The Power Configuration cluster is a Utility cluster, so by the spec, binds will not be created automatically using BDB Finding & Binding. Furthermore, BDB attribute reporting will only start reporting attributes which have an access type of Reportable, and by the specification, the only attribute in this cluster which has an access type of Reportable is the BatteryPercentageRemaining attribute.

    The clusters which BDB Finding & Binding will create binds for are defined in the structs bdb_ZclType1Clusters and bdb_ZclType2Clusters in bdb_FindingAndBinding.c, these are Application type clusters as defined by the spec.

    For more information about everything I just mentioned above, please refer to the ZCL v6 specification, the Base Device Behavior v1.0 specification, and the Zigbee Application Architecture v1.0 specification, available from the Zigbee Alliance website. Cluster role is defined under the "Overview > Classification" section of each cluster. Attribute access type is defined in the attribute table for each cluster.

    Now to answer your actual question. There are a few different solutions:

    1. Create a manual bind on this cluster from Server to Client using the ZDP_BindReq() API. Along with the API call to bdb_RepAddAttrCfgRecordDefaultToList() that you listed in your original post, these two things should cause the device to start periodically start reporting its BatteryPercentageRemaining to the Power Configuration client, assuming the bind is valid.

    2. 'Hack' BDB Finding & Binding on both devices by adding the Power Configuration Cluster to the struct for bdb_ZclType2Clusters on both devices. This will make it so BDB Finding & Binding will create the bind for you.

    3. Forget the bind and send a manual ZCL Attribute report to the other device using the API zcl_SendReportCmd()
  • Thank you Jason for the elaborative response on BDB Finding & Binding process. Being a novice, It helps me to understand understand Finding and Binding procedure.

    As you have mentioned i'm reading the  ZCL v6 specification and Base Device Behavior v1.0 specification but i could not find Zigbee Application Architecture v1.0 specification. When i google "ZigBee Application Architecture, ZigBee Alliance document 13-0589" (from ZCL specification and BDB docs) i end up in Zigbee Specification document. If you could share a direct link to ZigBee Application Architecture document it would help me.

    solution #1 - I'm confused on the manual bind procedure. I read many posts on queries regarding to binding, but i could not able to understand the procedure. I hope you can share some insights on how to perform a manual bind for my network configuration explained below

    In my network i have 5 ZED (battery operated) and and ZC (AC powered). All ZED report temperature value to ZC at a configured interval. Periodic reporting of temperature value works like a charm when i use SampleTemperatureSensor example as my ZED and SampleThermostat as my ZC. Now as a feature update i want to publish battery status to ZC. In this case were should i do the binding is it the ZED or ZC? how can i perform the bind request from these 5 ZED (individually) to ZC? Also, if i need to change the reporting interval of of battery status from ZED to ZC how can i achieve it from ZC?

    solution #2 - As we speak i read bdb_FindingAndBinding.c and as you mentioned i saw two structures bdb_ZclType1Clusters and bdb_ZclType2Clusters defined. I did hack the code and added ZCL_CLUSTER_ID_GEN_POWER_CFG to bdb_ZclType2Clusters list and ran my code again. This time i found that i can report attribute id ATTRID_POWER_CFG_BATTERY_PERCENTAGE_REMAINING to the client at a configured interval. I further dig deeper in to the code to understand the difference on why it worked after adding ZCL_CLUSTER_ID_GEN_POWER_CFG to bdb_ZclType2Clusters, i found that function bdb_checkMatchingEndpoints (in bdb_FindingAndBinding.c) looks for a matching cluster from simple descriptor response received from the client. Function bdb_checkMatchingEndpoints then search for any application cluster from the list and then add it to the binding table using the methods defined on BindingTable.c. Is this a valid approach?

    solution #3 - Correct me if my assumption on the argument list for zcl_SendReportCmd is right or not

    srcEP - sender endpoint

    dstAddr - what must be value that goes in this structure? For ex - my ZED ave successfully joined the network and how can i get coordinator address.

    realClusterID - ZCL_CLUSTER_ID_GEN_POWER_CFG

    zclReportCmd_t - i underand what must go in to this structure

    direction - is it ZCL_FRAME_SERVER_CLIENT_DIR?

    seqNum - bdb_getZCLFrameCounter()?

  • Hi Jason,

    Are the questions relating to solution #1 and #2 listed in my above post are valid? and my assumption for #3 valid?
  • Hi,

    As you mentioned i was able to create a manual bind from ZC to ZED but still i cannot able to see the attribute report functionality working.
  • Do you use sniffer to check if the binding is success?
  • Bind Request from ZC to ZED.cubx.zipYes please refer the attached sniffer log where the ZC bind request returns success in bind response reply from ZED.

  • I see the source address and destination address are the same in your bind requests. I suppose you should use coordinator address as destination.
  • Thank you YiKai for your quick response. Let me try it and update the results. Meanwhile I have couple of questions. Hope you can help me to understand the binding process  

    1. What is significance of of 1st argument and dstAddr, 2nd SourceAddr, and 5th DestinationAddr? I could not able to understand the description given in z-stack developer guide.

    2. Where does the binding table get stored? Is it on the ZED or ZC?

  • 1st DstAddr is the short address of destination of device you want to send binding command. It’s ZED in your case. 2nd SourceAddr means to tell the destination device that the source of binding device who will send message or command to binding DestinationAddr and it’s the IEEE address of your ZED. 5th DestinationAddr means the destination that device would do report or send command which in your case is ZC.
  • Thank you YiKai. I modified the code and it works. Thank you again for your help.

    Attached the sniffer log for reference.

    Bind Request from ZC to ZED_working.cubx.zip

  • Hi,Hari

    I have same question, can you share your code about reporting of battery voltage ?
    thank you!
  • Which version of Z-Stack are you using?

  • my version is z-stack3.0.1.
  • Use SampleTemperatureSensor as ZED and SampleThermostat as ZC with the following modifications to report battery voltage remaining data from ZED to ZC.

    Note:- this is for your reference and the files are taken from Z-Stack 3.0.1

    zcl_sampletemperaturesensor_data.c
    /**************************************************************************************************
      Filename:       zcl_sampletemperaturesensor_data.c
      Revised:        $Date: 2014-09-25 13:20:41 -0700 (Thu, 25 Sep 2014) $
      Revision:       $Revision: 40295 $
    
    
      Description:    Zigbee Cluster Library - sample device application.
    
    
      Copyright 2013-2014 Texas Instruments Incorporated. All rights reserved.
    
      IMPORTANT: Your use of this Software is limited to those specific rights
      granted under the terms of a software license agreement between the user
      who downloaded the software, his/her employer (which must be your employer)
      and Texas Instruments Incorporated (the "License").  You may not use this
      Software unless you agree to abide by the terms of the License. The License
      limits your use, and you acknowledge, that the Software may not be modified,
      copied or distributed unless embedded on a Texas Instruments microcontroller
      or used solely and exclusively in conjunction with a Texas Instruments radio
      frequency transceiver, which is integrated into your product.  Other than for
      the foregoing purpose, you may not use, reproduce, copy, prepare derivative
      works of, modify, distribute, perform, display or sell this Software and/or
      its documentation for any purpose.
    
      YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
      PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
      INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
      NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
      TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
      NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
      LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
      INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
      OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
      OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
      (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
    
      Should you have any questions regarding your right to use this Software,
      contact Texas Instruments Incorporated at www.TI.com.
    **************************************************************************************************/
    
    /*********************************************************************
     * INCLUDES
     */
    #include "ZComDef.h"
    #include "OSAL.h"
    #include "AF.h"
    #include "ZDConfig.h"
    
    #include "zcl.h"
    #include "zcl_general.h"
    #include "zcl_ha.h"
    #include "zcl_ms.h"
    
    #include "zcl_sampletemperaturesensor.h"
    
    /*********************************************************************
     * CONSTANTS
     */
    
    #define SAMPLETEMPERATURESENSOR_DEVICE_VERSION     0
    #define SAMPLETEMPERATURESENSOR_FLAGS              0
    
    #define SAMPLETEMPERATURESENSOR_HWVERSION          1
    #define SAMPLETEMPERATURESENSOR_ZCLVERSION         1
    
    #define SAMPLETEMPERATURESENSOR_MAX_MEASURED_VALUE  2700  // 27.00C
    #define SAMPLETEMPERATURESENSOR_MIN_MEASURED_VALUE  1700  // 17.00C
    
    #define SAMPLETEMPERATURESENSOR_MEASURED_VALUE      2000  // 20.00C
    
    /*********************************************************************
     * TYPEDEFS
     */
    
    /*********************************************************************
     * MACROS
     */
    
    /*********************************************************************
     * GLOBAL VARIABLES
     */
    
    // Global attributes
    const uint16 zclSampleTemperatureSensor_clusterRevision_all = 0x0001; 
    
    // Basic Cluster
    const uint8 zclSampleTemperatureSensor_HWRevision = SAMPLETEMPERATURESENSOR_HWVERSION;
    const uint8 zclSampleTemperatureSensor_ZCLVersion = SAMPLETEMPERATURESENSOR_ZCLVERSION;
    const uint8 zclSampleTemperatureSensor_ManufacturerName[] = { 16, 'T','e','x','a','s','I','n','s','t','r','u','m','e','n','t','s' };
    const uint8 zclSampleTemperatureSensor_ModelId[] = { 16, 'T','I','0','0','0','1',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ' };
    const uint8 zclSampleTemperatureSensor_DateCode[] = { 16, '2','0','0','6','0','8','3','1',' ',' ',' ',' ',' ',' ',' ',' ' };
    const uint8 zclSampleTemperatureSensor_PowerSource = POWER_SOURCE_MAINS_1_PHASE;
    
    uint8 zclSampleTemperatureSensor_LocationDescription[17];
    uint8 zclSampleTemperatureSensor_PhysicalEnvironment;
    uint8 zclSampleTemperatureSensor_DeviceEnable;
    
    // Identify Cluster
    uint16 zclSampleTemperatureSensor_IdentifyTime;
    
    // Temperature Sensor Cluster
    int16 zclSampleTemperatureSensor_MeasuredValue;
    const int16 zclSampleTemperatureSensor_MinMeasuredValue = SAMPLETEMPERATURESENSOR_MIN_MEASURED_VALUE; 
    const uint16 zclSampleTemperatureSensor_MaxMeasuredValue = SAMPLETEMPERATURESENSOR_MAX_MEASURED_VALUE;
    
    // Power configuration cluster
    uint8 zclSampleTemperatureSensor_battRemaining;
    
    /*********************************************************************
     * ATTRIBUTE DEFINITIONS - Uses REAL cluster IDs
     */
    
    // NOTE: The attributes listed in the AttrRec must be in ascending order 
    // per cluster to allow right function of the Foundation discovery commands
    
    CONST zclAttrRec_t zclSampleTemperatureSensor_Attrs[] =
    {
      // *** General Basic Cluster Attributes ***
      {
        ZCL_CLUSTER_ID_GEN_BASIC,
        { // Attribute record
          ATTRID_BASIC_ZCL_VERSION,
          ZCL_DATATYPE_UINT8,
          ACCESS_CONTROL_READ,
          (void *)&zclSampleTemperatureSensor_ZCLVersion
        }
      },
      {
        ZCL_CLUSTER_ID_GEN_BASIC,             // Cluster IDs - defined in the foundation (ie. zcl.h)
        {  // Attribute record
          ATTRID_BASIC_HW_VERSION,            // Attribute ID - Found in Cluster Library header (ie. zcl_general.h)
          ZCL_DATATYPE_UINT8,                 // Data Type - found in zcl.h
          ACCESS_CONTROL_READ,                // Variable access control - found in zcl.h
          (void *)&zclSampleTemperatureSensor_HWRevision  // Pointer to attribute variable
        }
      },
      {
        ZCL_CLUSTER_ID_GEN_BASIC,
        { // Attribute record
          ATTRID_BASIC_MANUFACTURER_NAME,
          ZCL_DATATYPE_CHAR_STR,
          ACCESS_CONTROL_READ,
          (void *)zclSampleTemperatureSensor_ManufacturerName
        }
      },
      {
        ZCL_CLUSTER_ID_GEN_BASIC,
        { // Attribute record
          ATTRID_BASIC_MODEL_ID,
          ZCL_DATATYPE_CHAR_STR,
          ACCESS_CONTROL_READ,
          (void *)zclSampleTemperatureSensor_ModelId
        }
      },
      {
        ZCL_CLUSTER_ID_GEN_BASIC,
        { // Attribute record
          ATTRID_BASIC_DATE_CODE,
          ZCL_DATATYPE_CHAR_STR,
          ACCESS_CONTROL_READ,
          (void *)zclSampleTemperatureSensor_DateCode
        }
      },
      {
        ZCL_CLUSTER_ID_GEN_BASIC,
        { // Attribute record
          ATTRID_BASIC_POWER_SOURCE,
          ZCL_DATATYPE_ENUM8,
          ACCESS_CONTROL_READ,
          (void *)&zclSampleTemperatureSensor_PowerSource
        }
      },
      {
        ZCL_CLUSTER_ID_GEN_BASIC,
        { // Attribute record
          ATTRID_BASIC_LOCATION_DESC,
          ZCL_DATATYPE_CHAR_STR,
          (ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE),
          (void *)zclSampleTemperatureSensor_LocationDescription
        }
      },
      {
        ZCL_CLUSTER_ID_GEN_BASIC,
        { // Attribute record
          ATTRID_BASIC_PHYSICAL_ENV,
          ZCL_DATATYPE_ENUM8,
          (ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE),
          (void *)&zclSampleTemperatureSensor_PhysicalEnvironment
        }
      },
      {
        ZCL_CLUSTER_ID_GEN_BASIC,
        { // Attribute record
          ATTRID_BASIC_DEVICE_ENABLED,
          ZCL_DATATYPE_BOOLEAN,
          (ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE),
          (void *)&zclSampleTemperatureSensor_DeviceEnable
        }
      },
      {
        ZCL_CLUSTER_ID_GEN_BASIC,
        {  // Attribute record
          ATTRID_CLUSTER_REVISION,
          ZCL_DATATYPE_UINT16,
          ACCESS_CONTROL_READ,
          (void *)&zclSampleTemperatureSensor_clusterRevision_all
        }
      },
    
      // *** Power Configuration Cluster ***
      {
        ZCL_CLUSTER_ID_GEN_POWER_CFG,
        {  // Attribute record
          ATTRID_POWER_CFG_BATTERY_PERCENTAGE_REMAINING,
          ZCL_DATATYPE_UINT8,
          ACCESS_CONTROL_READ | ACCESS_REPORTABLE,
          (void *)&zclSampleTemperatureSensor_battRemaining
        }
      },
    
      // *** Identify Cluster Attribute ***
      {
        ZCL_CLUSTER_ID_GEN_IDENTIFY,
        { // Attribute record
          ATTRID_IDENTIFY_TIME,
          ZCL_DATATYPE_UINT16,
          (ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE),
          (void *)&zclSampleTemperatureSensor_IdentifyTime
        }
      },
      {
        ZCL_CLUSTER_ID_GEN_IDENTIFY,
        {  // Attribute record
          ATTRID_CLUSTER_REVISION,
          ZCL_DATATYPE_UINT16,
          ACCESS_CONTROL_READ | ACCESS_GLOBAL,
          (void *)&zclSampleTemperatureSensor_clusterRevision_all
        }
      },
    
      // *** Temperature Measurement Attriubtes ***
      {
        ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT,
        { // Attribute record
          ATTRID_MS_TEMPERATURE_MEASURED_VALUE,
          ZCL_DATATYPE_INT16,
          ACCESS_CONTROL_READ | ACCESS_REPORTABLE,
          (void *)&zclSampleTemperatureSensor_MeasuredValue
        }
      },
      {
        ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT,
        { // Attribute record
          ATTRID_MS_TEMPERATURE_MIN_MEASURED_VALUE,
          ZCL_DATATYPE_INT16,
          ACCESS_CONTROL_READ,
          (void *)&zclSampleTemperatureSensor_MinMeasuredValue
        }
      },
      {
        ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT,
        { // Attribute record
          ATTRID_MS_TEMPERATURE_MAX_MEASURED_VALUE,
          ZCL_DATATYPE_INT16,
          ACCESS_CONTROL_READ,
          (void *)&zclSampleTemperatureSensor_MaxMeasuredValue
        }
      },
    
      {
        ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT,
        {  // Attribute record
          ATTRID_CLUSTER_REVISION,
          ZCL_DATATYPE_UINT16,
          ACCESS_CONTROL_READ,
          (void *)&zclSampleTemperatureSensor_clusterRevision_all
        }
      },
    };
    
    uint8 CONST zclSampleTemperatureSensor_NumAttributes = ( sizeof(zclSampleTemperatureSensor_Attrs) / sizeof(zclSampleTemperatureSensor_Attrs[0]) );
    
    /*********************************************************************
     * SIMPLE DESCRIPTOR
     */
    // This is the Cluster ID List and should be filled with Application
    // specific cluster IDs.
    #define ZCLSAMPLETEMPERATURESENSOR_MAX_INCLUSTERS       4
    const cId_t zclSampleTemperatureSensor_InClusterList[ZCLSAMPLETEMPERATURESENSOR_MAX_INCLUSTERS] =
    {
      ZCL_CLUSTER_ID_GEN_BASIC,
      ZCL_CLUSTER_ID_GEN_POWER_CFG,
      ZCL_CLUSTER_ID_GEN_IDENTIFY,
      ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT
    };
    
    #define ZCLSAMPLETEMPERATURESENSOR_MAX_OUTCLUSTERS       1
    const cId_t zclSampleTemperatureSensor_OutClusterList[ZCLSAMPLETEMPERATURESENSOR_MAX_OUTCLUSTERS] =
    {
      ZCL_CLUSTER_ID_GEN_IDENTIFY
    };
    
    SimpleDescriptionFormat_t zclSampleTemperatureSensor_SimpleDesc =
    {
      SAMPLETEMPERATURESENSOR_ENDPOINT,                  //  int Endpoint;
      ZCL_HA_PROFILE_ID,                                 //  uint16 AppProfId[2];
      ZCL_HA_DEVICEID_TEMPERATURE_SENSOR,                //  uint16 AppDeviceId[2];
      SAMPLETEMPERATURESENSOR_DEVICE_VERSION,            //  int   AppDevVer:4;
      SAMPLETEMPERATURESENSOR_FLAGS,                     //  int   AppFlags:4;
      ZCLSAMPLETEMPERATURESENSOR_MAX_INCLUSTERS,         //  byte  AppNumInClusters;
      (cId_t *)zclSampleTemperatureSensor_InClusterList, //  byte *pAppInClusterList;
      ZCLSAMPLETEMPERATURESENSOR_MAX_OUTCLUSTERS,        //  byte  AppNumInClusters;
      (cId_t *)zclSampleTemperatureSensor_OutClusterList //  byte *pAppInClusterList;
    };
     
    /*********************************************************************
     * GLOBAL FUNCTIONS
     */
    
    /*********************************************************************
     * LOCAL FUNCTIONS
     */
    
    /*********************************************************************
     * @fn      zclSampleLight_ResetAttributesToDefaultValues
     *
     * @brief   Reset all writable attributes to their default values.
     *
     * @param   none
     *
     * @return  none
     */
    void zclSampleTemperatureSensor_ResetAttributesToDefaultValues(void)
    {
      int i;
      
      zclSampleTemperatureSensor_LocationDescription[0] = 16;
      for (i = 1; i <= 16; i++)
      {
        zclSampleTemperatureSensor_LocationDescription[i] = ' ';
      }
      
      zclSampleTemperatureSensor_PhysicalEnvironment = PHY_UNSPECIFIED_ENV;
      zclSampleTemperatureSensor_DeviceEnable = DEVICE_ENABLED;
      
    #ifdef ZCL_IDENTIFY
      zclSampleTemperatureSensor_IdentifyTime = 0;
    #endif
      
      zclSampleTemperatureSensor_MeasuredValue = SAMPLETEMPERATURESENSOR_MEASURED_VALUE;
      
    }
    
    /****************************************************************************
    ****************************************************************************/
    
    
    
    zcl_sampletemperaturesensor.c
    /**************************************************************************************************
      Filename:       zcl_sampletemperaturesensor.c
      Revised:        $Date: 2014-10-24 16:04:46 -0700 (Fri, 24 Oct 2014) $
      Revision:       $Revision: 40796 $
    
      Description:    Zigbee Cluster Library - sample device application.
    
    
      Copyright 2013 Texas Instruments Incorporated. All rights reserved.
    
      IMPORTANT: Your use of this Software is limited to those specific rights
      granted under the terms of a software license agreement between the user
      who downloaded the software, his/her employer (which must be your employer)
      and Texas Instruments Incorporated (the "License").  You may not use this
      Software unless you agree to abide by the terms of the License. The License
      limits your use, and you acknowledge, that the Software may not be modified,
      copied or distributed unless embedded on a Texas Instruments microcontroller
      or used solely and exclusively in conjunction with a Texas Instruments radio
      frequency transceiver, which is integrated into your product.  Other than for
      the foregoing purpose, you may not use, reproduce, copy, prepare derivative
      works of, modify, distribute, perform, display or sell this Software and/or
      its documentation for any purpose.
    
      YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
      PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
      INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
      NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
      TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
      NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
      LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
      INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
      OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
      OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
      (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
    
      Should you have any questions regarding your right to use this Software,
      contact Texas Instruments Incorporated at www.TI.com.
    **************************************************************************************************/
    
    /*********************************************************************
      This application implements a ZigBee Temperature Sensor, based on Z-Stack 3.0.
    
      This application is based on the common sample-application user interface. Please see the main
      comment in zcl_sampleapp_ui.c. The rest of this comment describes only the content specific for
      this sample applicetion.
      
      Application-specific UI peripherals being used:
    
      - LEDs:
        LED1 is not used in this application
    
      Application-specific menu system:
    
        <SET LOCAL TEMP> Set the temperature of the local temperature sensor
          Up/Down changes the temperature 
          This screen shows the following information:
            Line2:
              Shows the temperature of the local temperature sensor
    
    *********************************************************************/
    
    /*********************************************************************
     * INCLUDES
     */
    #include "ZComDef.h"
    #include "OSAL.h"
    #include "AF.h"
    #include "ZDApp.h"
    #include "ZDObject.h"
    #include "ZDProfile.h"
    #include "MT_SYS.h"
    
    #include "zcl.h"
    #include "zcl_general.h"
    #include "zcl_ha.h"
    #include "zcl_ms.h"
    
    #include "zcl_sampletemperaturesensor.h"
    
    #include "onboard.h"
    
    /* HAL */
    #include "hal_lcd.h"
    #include "hal_led.h"
    #include "hal_key.h"
    
    #include "bdb_interface.h"
    #include "bdb_Reporting.h"
    
    #include "zcl_sampleapps_ui.h"
       
    /*********************************************************************
     * MACROS
     */
    
    // how often to report temperature
    #define SAMPLETEMPERATURESENSOR_REPORT_INTERVAL   10000
    
    #define GUI_LOCAL_TEMP    1
    
    #define APP_TITLE "   Temp Sensor  "
    
    /*********************************************************************
     * CONSTANTS
     */
    
    /*********************************************************************
     * TYPEDEFS
     */
    
    /*********************************************************************
     * GLOBAL VARIABLES
     */
    byte zclSampleTemperatureSensor_TaskID;
    
    extern int16 zdpExternalStateTaskID;
    
    /*********************************************************************
     * GLOBAL FUNCTIONS
     */
    
    /*********************************************************************
     * LOCAL VARIABLES
     */
    
    devStates_t zclSampleTemperatureSensor_NwkState = DEV_INIT;
    
    //static uint8 aProcessCmd[] = { 1, 0, 0, 0 }; // used for reset command, { length + cmd0 + cmd1 + data }
    
    // Test Endpoint to allow SYS_APP_MSGs
    /*
    static endPointDesc_t sampleTemperatureSensor_TestEp =
    {
      20,                                 // Test endpoint
      0,
      &zclSampleTemperatureSensor_TaskID,
      (SimpleDescriptionFormat_t *)NULL,  // No Simple description for this test endpoint
      (afNetworkLatencyReq_t)0            // No Network Latency req
    };
    */
    #ifdef BDB_REPORTING
    #if BDBREPORTING_MAX_ANALOG_ATTR_SIZE == 8
      uint8 reportableChange[] = {0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // 0x2C01 is 300 in int16
    #endif
    #if BDBREPORTING_MAX_ANALOG_ATTR_SIZE == 4
      uint8 reportableChange[] = {0x2C, 0x01, 0x00, 0x00}; // 0x2C01 is 300 in int16
    #endif 
    #if BDBREPORTING_MAX_ANALOG_ATTR_SIZE == 2
      uint8 reportableChange[] = {0x2C, 0x01}; // 0x2C01 is 300 in int16
    #endif 
    #endif
    
    /*********************************************************************
     * LOCAL FUNCTIONS
     */
    static void zclSampleTemperatureSensor_HandleKeys( byte shift, byte keys );
    static void zclSampleTemperatureSensor_BasicResetCB( void );
    
    static void zclSampleTemperatureSensor_ProcessCommissioningStatus(bdbCommissioningModeMsg_t* bdbCommissioningModeMsg);
    
    // Functions to process ZCL Foundation incoming Command/Response messages
    static void zclSampleTemperatureSensor_ProcessIncomingMsg( zclIncomingMsg_t *msg );
    #ifdef ZCL_READ
    static uint8 zclSampleTemperatureSensor_ProcessInReadRspCmd( zclIncomingMsg_t *pInMsg );
    #endif
    #ifdef ZCL_WRITE
    static uint8 zclSampleTemperatureSensor_ProcessInWriteRspCmd( zclIncomingMsg_t *pInMsg );
    #endif
    static uint8 zclSampleTemperatureSensor_ProcessInDefaultRspCmd( zclIncomingMsg_t *pInMsg );
    #ifdef ZCL_DISCOVER
    static uint8 zclSampleTemperatureSensor_ProcessInDiscCmdsRspCmd( zclIncomingMsg_t *pInMsg );
    static uint8 zclSampleTemperatureSensor_ProcessInDiscAttrsRspCmd( zclIncomingMsg_t *pInMsg );
    static uint8 zclSampleTemperatureSensor_ProcessInDiscAttrsExtRspCmd( zclIncomingMsg_t *pInMsg );
    #endif // ZCL_DISCOVER
    
    static void zclSampleTemperatureSensor_UiActionChangeTemp(uint16 keys);
    
    void zclSampleTemperatureSensor_uiAppUpdateLcd(uint8 uiCurrentState, char * line[3]);
    
    /*********************************************************************
     * STATUS STRINGS
     */
    
    /*********************************************************************
     * CONSTANTS
     */
    const uiState_t zclSampleTemperatureSensor_uiAppStatesMain[] =
    {
      /*  UI_STATE_BACK_FROM_APP_MENU  */   {UI_STATE_DEFAULT_MOVE, GUI_LOCAL_TEMP, UI_KEY_SW_5_PRESSED, &UI_ActionBackFromAppMenu}, //do not change this line, except for the second item, which should point to the last entry in this menu
      /*  GUI_LOCAL_TEMP          */        {UI_STATE_BACK_FROM_APP_MENU, UI_STATE_DEFAULT_MOVE, UI_KEY_SW_1_PRESSED | UI_KEY_SW_3_PRESSED, &zclSampleTemperatureSensor_UiActionChangeTemp},
    };
    
    /*********************************************************************
     * ZCL General Profile Callback table
     */
    static zclGeneral_AppCallbacks_t zclSampleTemperatureSensor_CmdCallbacks =
    {
      zclSampleTemperatureSensor_BasicResetCB,        // Basic Cluster Reset command
      NULL,                                           // Identify Trigger Effect command
      NULL,             				                      // On/Off cluster command
      NULL,                                           // On/Off cluster enhanced command Off with Effect
      NULL,                                           // On/Off cluster enhanced command On with Recall Global Scene
      NULL,                                           // On/Off cluster enhanced command On with Timed Off
    #ifdef ZCL_LEVEL_CTRL
      NULL,                                           // Level Control Move to Level command
      NULL,                                           // Level Control Move command
      NULL,                                           // Level Control Step command
      NULL,                                           // Level Control Stop command
    #endif
    #ifdef ZCL_GROUPS
      NULL,                                           // Group Response commands
    #endif
    #ifdef ZCL_SCENES
      NULL,                                           // Scene Store Request command
      NULL,                                           // Scene Recall Request command
      NULL,                                           // Scene Response command
    #endif
    #ifdef ZCL_ALARMS
      NULL,                                           // Alarm (Response) commands
    #endif
    #ifdef SE_UK_EXT
      NULL,                                           // Get Event Log command
      NULL,                                           // Publish Event Log command
    #endif
      NULL,                                           // RSSI Location command
      NULL                                            // RSSI Location Response command
    };
    
    /*********************************************************************
     * @fn          zclSampleTemperatureSensor_Init
     *
     * @brief       Initialization function for the zclGeneral layer.
     *
     * @param       none
     *
     * @return      none
     */
    void zclSampleTemperatureSensor_Init( byte task_id )
    {
      zclSampleTemperatureSensor_TaskID = task_id;
    
      // Register the Simple Descriptor for this application
      bdb_RegisterSimpleDescriptor( &zclSampleTemperatureSensor_SimpleDesc ); 
      
      // Register the ZCL General Cluster Library callback functions
      zclGeneral_RegisterCmdCallbacks( SAMPLETEMPERATURESENSOR_ENDPOINT, &zclSampleTemperatureSensor_CmdCallbacks );
    
      // Register the application's attribute list
      zclSampleTemperatureSensor_ResetAttributesToDefaultValues();
      zcl_registerAttrList( SAMPLETEMPERATURESENSOR_ENDPOINT, zclSampleTemperatureSensor_NumAttributes, zclSampleTemperatureSensor_Attrs );   
    
      // Register the Application to receive the unprocessed Foundation command/response messages
      zcl_registerForMsg( zclSampleTemperatureSensor_TaskID );
    
      // Register for all key events - This app will handle all key events
      RegisterForKeys( zclSampleTemperatureSensor_TaskID );
    
      bdb_RegisterCommissioningStatusCB( zclSampleTemperatureSensor_ProcessCommissioningStatus );
    
    #ifdef BDB_REPORTING
      //Adds the default configuration values for the temperature attribute of the ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT cluster, for endpoint SAMPLETEMPERATURESENSOR_ENDPOINT
      //Default maxReportingInterval value is 10 seconds
      //Default minReportingInterval value is 3 seconds
      //Default reportChange value is 300 (3 degrees)
      bdb_RepAddAttrCfgRecordDefaultToList(SAMPLETEMPERATURESENSOR_ENDPOINT, ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT, ATTRID_MS_TEMPERATURE_MEASURED_VALUE, 0, 10, reportableChange);
      bdb_RepAddAttrCfgRecordDefaultToList(SAMPLETEMPERATURESENSOR_ENDPOINT, ZCL_CLUSTER_ID_GEN_POWER_CFG, ATTRID_POWER_CFG_BATTERY_PERCENTAGE_REMAINING, 0, 10, reportableChange);
    #endif
      
      zdpExternalStateTaskID = zclSampleTemperatureSensor_TaskID;
    
      UI_Init(zclSampleTemperatureSensor_TaskID, SAMPLEAPP_LCD_AUTO_UPDATE_EVT, SAMPLEAPP_KEY_AUTO_REPEAT_EVT, &zclSampleTemperatureSensor_IdentifyTime, APP_TITLE, zclSampleTemperatureSensor_uiAppUpdateLcd, zclSampleTemperatureSensor_uiAppStatesMain);
    
      UI_UpdateLcd();  
    }
    
    /*********************************************************************
     * @fn          zclSample_event_loop
     *
     * @brief       Event Loop Processor for zclGeneral.
     *
     * @param       none
     *
     * @return      none
     */
    uint16 zclSampleTemperatureSensor_event_loop( uint8 task_id, uint16 events )
    {
      afIncomingMSGPacket_t *MSGpkt;
    
      (void)task_id;  // Intentionally unreferenced parameter
    
      if ( events & SYS_EVENT_MSG )
      {
        while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( zclSampleTemperatureSensor_TaskID )) )
        {
          switch ( MSGpkt->hdr.event )
          {
            case ZCL_INCOMING_MSG:
              // Incoming ZCL Foundation command/response messages
              zclSampleTemperatureSensor_ProcessIncomingMsg( (zclIncomingMsg_t *)MSGpkt );
              break;
    
            case KEY_CHANGE:
              zclSampleTemperatureSensor_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
              break;
    
            case ZDO_STATE_CHANGE:
              UI_DeviceStateUpdated((devStates_t)(MSGpkt->hdr.status));
              break;
    
            default:
              break;
          }
    
          // Release the memory
          osal_msg_deallocate( (uint8 *)MSGpkt );
        }
    
        // return unprocessed events
        return (events ^ SYS_EVENT_MSG);
      }
      
    #if ZG_BUILD_ENDDEVICE_TYPE    
      if ( events & SAMPLEAPP_END_DEVICE_REJOIN_EVT )
      {
        bdb_ZedAttemptRecoverNwk();
        return ( events ^ SAMPLEAPP_END_DEVICE_REJOIN_EVT );
      }
    #endif
    
      if ( events & SAMPLEAPP_LCD_AUTO_UPDATE_EVT )
      {
        UI_UpdateLcd();
        return ( events ^ SAMPLEAPP_LCD_AUTO_UPDATE_EVT );
      }
    
      if ( events & SAMPLEAPP_KEY_AUTO_REPEAT_EVT )
      {
        UI_MainStateMachine(UI_KEY_AUTO_PRESSED);
        return ( events ^ SAMPLEAPP_KEY_AUTO_REPEAT_EVT );
      }
    
      // Discard unknown events
      return 0;
    }
    
    /*********************************************************************
     * @fn      zclSampleTemperatureSensor_HandleKeys
     *
     * @brief   Handles all key events for this device.
     *
     * @param   shift - true if in shift/alt.
     * @param   keys - bit field for key events. Valid entries:
     *                 HAL_KEY_SW_5
     *                 HAL_KEY_SW_4
     *                 HAL_KEY_SW_3
     *                 HAL_KEY_SW_2
     *                 HAL_KEY_SW_1
     *
     * @return  none
     */
    static void zclSampleTemperatureSensor_HandleKeys( byte shift, byte keys )
    {
      UI_MainStateMachine(keys);
    }
    
    /*********************************************************************
     * @fn      zclSampleTemperatureSensor_LcdDisplayMainMode
     *
     * @brief   Called to display the main screen on the LCD.
     *
     * @param   none
     *
     * @return  none
     */
    static void zclSampleTemperatureSensor_ProcessCommissioningStatus(bdbCommissioningModeMsg_t* bdbCommissioningModeMsg)
    {
        switch(bdbCommissioningModeMsg->bdbCommissioningMode)
        {
          case BDB_COMMISSIONING_FORMATION:
            if(bdbCommissioningModeMsg->bdbCommissioningStatus == BDB_COMMISSIONING_SUCCESS)
            {
              //After formation, perform nwk steering again plus the remaining commissioning modes that has not been process yet
              bdb_StartCommissioning(BDB_COMMISSIONING_MODE_NWK_STEERING | bdbCommissioningModeMsg->bdbRemainingCommissioningModes);
            }
            else
            {
              //Want to try other channels?
              //try with bdb_setChannelAttribute
            }
          break;
          case BDB_COMMISSIONING_NWK_STEERING:
            if(bdbCommissioningModeMsg->bdbCommissioningStatus == BDB_COMMISSIONING_SUCCESS)
            {
              //YOUR JOB:
              //We are on the nwk, what now?
            }
            else
            {
              //See the possible errors for nwk steering procedure
              //No suitable networks found
              //Want to try other channels?
              //try with bdb_setChannelAttribute
            }
          break;
          case BDB_COMMISSIONING_FINDING_BINDING:
            if(bdbCommissioningModeMsg->bdbCommissioningStatus == BDB_COMMISSIONING_SUCCESS)
            {
              //YOUR JOB:
            }
            else
            {
              //YOUR JOB:
              //retry?, wait for user interaction?
            }
          break;
          case BDB_COMMISSIONING_INITIALIZATION:
            //Initialization notification can only be successful. Failure on initialization 
            //only happens for ZED and is notified as BDB_COMMISSIONING_PARENT_LOST notification
            
            //YOUR JOB:
            //We are on a network, what now?
            
          break;
    #if ZG_BUILD_ENDDEVICE_TYPE    
        case BDB_COMMISSIONING_PARENT_LOST:
          if(bdbCommissioningModeMsg->bdbCommissioningStatus == BDB_COMMISSIONING_NETWORK_RESTORED)
          {
            //We did recover from losing parent
          }
          else
          {
            //Parent not found, attempt to rejoin again after a fixed delay
            osal_start_timerEx(zclSampleTemperatureSensor_TaskID, SAMPLEAPP_END_DEVICE_REJOIN_EVT, SAMPLEAPP_END_DEVICE_REJOIN_DELAY);
          }
        break;
    #endif 
        }
    
      UI_UpdateComissioningStatus(bdbCommissioningModeMsg);
    }
    
    /*********************************************************************
     * @fn      zclSampleTemperatureSensor_BasicResetCB
     *
     * @brief   Callback from the ZCL General Cluster Library
     *          to set all the Basic Cluster attributes to default values.
     *
     * @param   none
     *
     * @return  none
     */
    static void zclSampleTemperatureSensor_BasicResetCB( void )
    {
      zclSampleTemperatureSensor_ResetAttributesToDefaultValues();
      
      UI_UpdateLcd();
    }
    
    /******************************************************************************
     *
     *  Functions for processing ZCL Foundation incoming Command/Response messages
     *
     *****************************************************************************/
    
    /*********************************************************************
     * @fn      zclSampleTemperatureSensor_ProcessIncomingMsg
     *
     * @brief   Process ZCL Foundation incoming message
     *
     * @param   pInMsg - pointer to the received message
     *
     * @return  none
     */
    static void zclSampleTemperatureSensor_ProcessIncomingMsg( zclIncomingMsg_t *pInMsg)
    {
      switch ( pInMsg->zclHdr.commandID )
      {
    #ifdef ZCL_READ
        case ZCL_CMD_READ_RSP:
          zclSampleTemperatureSensor_ProcessInReadRspCmd( pInMsg );
          break;
    #endif
    #ifdef ZCL_WRITE
        case ZCL_CMD_WRITE_RSP:
          zclSampleTemperatureSensor_ProcessInWriteRspCmd( pInMsg );
          break;
    #endif
    #ifdef ZCL_REPORT
        // See ZCL Test Applicaiton (zcl_testapp.c) for sample code on Attribute Reporting
        case ZCL_CMD_CONFIG_REPORT:
          //zclSampleTemperatureSensor_ProcessInConfigReportCmd( pInMsg );
          break;
          case ZCL_CMD_READ_REPORT_CFG:
          //zclSampleTemperatureSensor_ProcessInReadReportCfgCmd( pInMsg );
          break;
        case ZCL_CMD_CONFIG_REPORT_RSP:
          //zclSampleTemperatureSensor_ProcessInConfigReportRspCmd( pInMsg );
          break;
        case ZCL_CMD_READ_REPORT_CFG_RSP:
          //zclSampleTemperatureSensor_ProcessInReadReportCfgRspCmd( pInMsg );
          break;
    
        case ZCL_CMD_REPORT:
          //zclSampleTemperatureSensor_ProcessInReportCmd( pInMsg );
          break;
    #endif
        case ZCL_CMD_DEFAULT_RSP:
          zclSampleTemperatureSensor_ProcessInDefaultRspCmd( pInMsg );
          break;
    #ifdef ZCL_DISCOVER
        case ZCL_CMD_DISCOVER_CMDS_RECEIVED_RSP:
          zclSampleTemperatureSensor_ProcessInDiscCmdsRspCmd( pInMsg );
          break;
    
        case ZCL_CMD_DISCOVER_CMDS_GEN_RSP:
          zclSampleTemperatureSensor_ProcessInDiscCmdsRspCmd( pInMsg );
          break;
    
        case ZCL_CMD_DISCOVER_ATTRS_RSP:
          zclSampleTemperatureSensor_ProcessInDiscAttrsRspCmd( pInMsg );
          break;
    
        case ZCL_CMD_DISCOVER_ATTRS_EXT_RSP:
          zclSampleTemperatureSensor_ProcessInDiscAttrsExtRspCmd( pInMsg );
          break;
    #endif
        default:
          break;
      }
    
      if ( pInMsg->attrCmd )
      {
        osal_mem_free( pInMsg->attrCmd );
      }
    }
    
    #ifdef ZCL_READ
    /*********************************************************************
     * @fn      zclSampleTemperatureSensor_ProcessInReadRspCmd
     *
     * @brief   Process the "Profile" Read Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclSampleTemperatureSensor_ProcessInReadRspCmd( zclIncomingMsg_t *pInMsg )
    {
      zclReadRspCmd_t *readRspCmd;
      uint8 i;
    
      readRspCmd = (zclReadRspCmd_t *)pInMsg->attrCmd;
      for ( i = 0; i < readRspCmd->numAttr; i++ )
      {
        // Notify the originator of the results of the original read attributes
        // attempt and, for each successfull request, the value of the requested
        // attribute
      }
    
      return ( TRUE );
    }
    #endif // ZCL_READ
    
    #ifdef ZCL_WRITE
    /*********************************************************************
     * @fn      zclSampleTemperatureSensor_ProcessInWriteRspCmd
     *
     * @brief   Process the "Profile" Write Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclSampleTemperatureSensor_ProcessInWriteRspCmd( zclIncomingMsg_t *pInMsg )
    {
      zclWriteRspCmd_t *writeRspCmd;
      uint8 i;
    
      writeRspCmd = (zclWriteRspCmd_t *)pInMsg->attrCmd;
      for ( i = 0; i < writeRspCmd->numAttr; i++ )
      {
        // Notify the device of the results of the its original write attributes
        // command.
      }
    
      return ( TRUE );
    }
    #endif // ZCL_WRITE
    
    /*********************************************************************
     * @fn      zclSampleTemperatureSensor_ProcessInDefaultRspCmd
     *
     * @brief   Process the "Profile" Default Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclSampleTemperatureSensor_ProcessInDefaultRspCmd( zclIncomingMsg_t *pInMsg )
    {
      // zclDefaultRspCmd_t *defaultRspCmd = (zclDefaultRspCmd_t *)pInMsg->attrCmd;
    
      // Device is notified of the Default Response command.
      (void)pInMsg;
    
      return ( TRUE );
    }
    
    #ifdef ZCL_DISCOVER
    /*********************************************************************
     * @fn      zclSampleTemperatureSensor_ProcessInDiscCmdsRspCmd
     *
     * @brief   Process the Discover Commands Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclSampleTemperatureSensor_ProcessInDiscCmdsRspCmd( zclIncomingMsg_t *pInMsg )
    {
      zclDiscoverCmdsCmdRsp_t *discoverRspCmd;
      uint8 i;
    
      discoverRspCmd = (zclDiscoverCmdsCmdRsp_t *)pInMsg->attrCmd;
      for ( i = 0; i < discoverRspCmd->numCmd; i++ )
      {
        // Device is notified of the result of its attribute discovery command.
      }
    
      return ( TRUE );
    }
    
    /*********************************************************************
     * @fn      zclSampleTemperatureSensor_ProcessInDiscAttrsRspCmd
     *
     * @brief   Process the "Profile" Discover Attributes Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclSampleTemperatureSensor_ProcessInDiscAttrsRspCmd( zclIncomingMsg_t *pInMsg )
    {
      zclDiscoverAttrsRspCmd_t *discoverRspCmd;
      uint8 i;
    
      discoverRspCmd = (zclDiscoverAttrsRspCmd_t *)pInMsg->attrCmd;
      for ( i = 0; i < discoverRspCmd->numAttr; i++ )
      {
        // Device is notified of the result of its attribute discovery command.
      }
    
      return ( TRUE );
    }
    
    /*********************************************************************
     * @fn      zclSampleTemperatureSensor_ProcessInDiscAttrsExtRspCmd
     *
     * @brief   Process the "Profile" Discover Attributes Extended Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclSampleTemperatureSensor_ProcessInDiscAttrsExtRspCmd( zclIncomingMsg_t *pInMsg )
    {
      zclDiscoverAttrsExtRsp_t *discoverRspCmd;
      uint8 i;
    
      discoverRspCmd = (zclDiscoverAttrsExtRsp_t *)pInMsg->attrCmd;
      for ( i = 0; i < discoverRspCmd->numAttr; i++ )
      {
        // Device is notified of the result of its attribute discovery command.
      }
    
      return ( TRUE );
    }
    #endif // ZCL_DISCOVER
    
    // GUI_LOCAL_TEMP
    static void zclSampleTemperatureSensor_UiActionChangeTemp(uint16 keys)
    {
      if ( keys & HAL_KEY_SW_1 )
      {
        // increase the temperature
        if ( zclSampleTemperatureSensor_MeasuredValue < zclSampleTemperatureSensor_MaxMeasuredValue )
        {
          zclSampleTemperatureSensor_MeasuredValue = zclSampleTemperatureSensor_MeasuredValue + 100;  // considering using whole number value
    #ifdef BDB_REPORTING      
          uint8 status = bdb_RepChangedAttrValue(SAMPLETEMPERATURESENSOR_ENDPOINT, ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT, ATTRID_MS_TEMPERATURE_MEASURED_VALUE);
    #endif
        }
        else if ( zclSampleTemperatureSensor_MeasuredValue >= zclSampleTemperatureSensor_MaxMeasuredValue )
        {
          zclSampleTemperatureSensor_MeasuredValue = zclSampleTemperatureSensor_MaxMeasuredValue;
        }
      }
      
      if ( keys & HAL_KEY_SW_3 )
      {
        // decrease the temperature
        if ( zclSampleTemperatureSensor_MeasuredValue > zclSampleTemperatureSensor_MinMeasuredValue )
        {
          zclSampleTemperatureSensor_MeasuredValue = zclSampleTemperatureSensor_MeasuredValue - 100;  // considering using whole number value
    #ifdef BDB_REPORTING
          uint8 status = bdb_RepChangedAttrValue(SAMPLETEMPERATURESENSOR_ENDPOINT, ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT, ATTRID_MS_TEMPERATURE_MEASURED_VALUE);
    #endif
        }
        else if ( zclSampleTemperatureSensor_MeasuredValue <= zclSampleTemperatureSensor_MinMeasuredValue )
        {
          zclSampleTemperatureSensor_MeasuredValue = zclSampleTemperatureSensor_MinMeasuredValue;
        }
      }
      
      UI_UpdateLcd();
    }
    
    
    void zclSampleTemperatureSensor_uiAppUpdateLcd(uint8 gui_state, char * line[3])
    {
      static char sDisplayTemp[16];
      
      switch(gui_state)
      {
        case GUI_LOCAL_TEMP:
        // display current temperature
        osal_memcpy(sDisplayTemp, "TEMP: ", 6);
        _ltoa( ( zclSampleTemperatureSensor_MeasuredValue / 100 ), (void *)(&sDisplayTemp[6]), 10 );   // convert temperature to whole number
        osal_memcpy( &sDisplayTemp[8], "C", 2 );
    
        line[1] = (char *)sDisplayTemp;
        line[2] = "<SET LOCAL TEMP>";
        break;
        
        default:
        break;
      }
    }
    
    /****************************************************************************
    ****************************************************************************/
    
    
    

    bdb_FindingAndBinding.c
    /**************************************************************************************************
      Filename:       bdb_FindingAndBinding.c
      Revised:        $Date: 2016-02-25 11:51:49 -0700 (Thu, 25 Feb 2016) $
      Revision:       $Revision: - $
    
      Description:    This file contains the Base Device Behavior functions and attributes.
    
    
      Copyright 2006-2015 Texas Instruments Incorporated. All rights reserved.
    
      IMPORTANT: Your use of this Software is limited to those specific rights
      granted under the terms of a software license agreement between the user
      who downloaded the software, his/her employer (which must be your employer)
      and Texas Instruments Incorporated (the "License").  You may not use this
      Software unless you agree to abide by the terms of the License. The License
      limits your use, and you acknowledge, that the Software may not be modified,
      copied or distributed unless embedded on a Texas Instruments microcontroller
      or used solely and exclusively in conjunction with a Texas Instruments radio
      frequency transceiver, which is integrated into your product.  Other than for
      the foregoing purpose, you may not use, reproduce, copy, prepare derivative
      works of, modify, distribute, perform, display or sell this Software and/or
      its documentation for any purpose.
    
      YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
      PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
      INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
      NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
      TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
      NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
      LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
      INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
      OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
      OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
      (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
    
      Should you have any questions regarding your right to use this Software,
      contact Texas Instruments Incorporated at www.TI.com.
    **************************************************************************************************/
    
    /*********************************************************************
     * INCLUDES
     */
    
    #include "bdb.h"
    #include "ZDObject.h"
    #include "bdb_interface.h"
    #include "AddrMgr.h"
       
    #if (BDB_FINDING_BINDING_CAPABILITY_ENABLED==1)   
       
    /*********************************************************************
     * MACROS
     */
    
    
    
       
    /*********************************************************************
     * CONSTANTS
     */
    /*********************************************************************
     * TYPEDEFS
     */
     
     
    /*********************************************************************
     * GLOBAL VARIABLES
     */
    
    uint8 grpName[6] = {'G','r','o','u','p','\0'};
    bdbGCB_IdentifyTimeChange_t      pfnIdentifyTimeChangeCB = NULL; 
    bdbGCB_BindNotification_t        pfnBindNotificationCB = NULL;
    
    /*********************************************************************
     * EXTERNAL VARIABLES
     */
    
    /*********************************************************************
     * EXTERNAL FUNCTIONS
     */
    
    
    
    /*********************************************************************
     * LOCAL VARIABLES
     */
    
    SimpleDescriptionFormat_t  bdb_FindingBindingTargetSimpleDesc;
    
    uint8 bdbIndentifyActiveEndpoint  = 0xFF;
    
    //Your JOB:
    //Remove the clusters that your application do not use. This will save some flash and processing
    //when looking into matching clusters during the finding & binding procedure
    const cId_t bdb_ZclType1Clusters[] =
    {
      ZCL_CLUSTER_ID_GEN_SCENES,
      ZCL_CLUSTER_ID_GEN_ON_OFF,
      ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL,
      ZCL_CLUSTER_ID_GEN_ALARMS,
      ZCL_CLUSTER_ID_GEN_PARTITION,
      ZCL_CLUSTER_ID_CLOSURES_WINDOW_COVERING,
      ZCL_CLUSTER_ID_HVAC_FAN_CONTROL,
      ZCL_CLUSTER_ID_HVAC_DIHUMIDIFICATION_CONTROL,
      ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL,
      ZCL_CLUSTER_ID_LIGHTING_BALLAST_CONFIG,
      ZCL_CLUSTER_ID_SS_IAS_ACE,
      ZCL_CLUSTER_ID_SS_IAS_WD,
      ZCL_CLUSTER_ID_PI_GENERIC_TUNNEL,
      ZCL_CLUSTER_ID_PI_BACNET_PROTOCOL_TUNNEL,
      ZCL_CLUSTER_ID_HA_ELECTRICAL_MEASUREMENT,
      ZCL_CLUSTER_ID_PI_11073_PROTOCOL_TUNNEL,
      ZCL_CLUSTER_ID_PI_ISO7818_PROTOCOL_TUNNEL,
      ZCL_CLUSTER_ID_PI_RETAIL_TUNNEL,
      ZCL_CLUSTER_ID_SE_PRICE,
      ZCL_CLUSTER_ID_SE_DRLC,
      ZCL_CLUSTER_ID_SE_METERING,
      ZCL_CLUSTER_ID_SE_MESSAGING,
      ZCL_CLUSTER_ID_TELECOMMUNICATIONS_INFORMATION,
      ZCL_CLUSTER_ID_TELECOMMUNICATIONS_VOICE_OVER_ZIGBEE,
    };
    
    //Your JOB:
    //Remove the clusters that your application do not use. This will save some flash and processing
    //when looking into matching clusters during the finding & binding procedure
    const cId_t bdb_ZclType2Clusters[] =
    {
      ZCL_CLUSTER_ID_GEN_POWER_CFG,
      ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG,
      ZCL_CLUSTER_ID_GEN_TIME,
      ZCL_CLUSTER_ID_GEN_ANALOG_INPUT_BASIC,
      ZCL_CLUSTER_ID_GEN_ANALOG_OUTPUT_BASIC,
      ZCL_CLUSTER_ID_GEN_ANALOG_VALUE_BASIC,
      ZCL_CLUSTER_ID_GEN_BINARY_INPUT_BASIC,
      ZCL_CLUSTER_ID_GEN_BINARY_OUTPUT_BASIC,
      ZCL_CLUSTER_ID_GEN_BINARY_VALUE_BASIC,
      ZCL_CLUSTER_ID_GEN_MULTISTATE_INPUT_BASIC,
      ZCL_CLUSTER_ID_GEN_MULTISTATE_OUTPUT_BASIC,
      ZCL_CLUSTER_ID_GEN_MULTISTATE_VALUE_BASIC,
      ZCL_CLUSTER_ID_OTA,
      ZCL_CLUSTER_ID_GEN_APPLIANCE_CONTROL,
      ZCL_CLUSTER_ID_CLOSURES_SHADE_CONFIG,
      ZCL_CLUSTER_ID_CLOSURES_DOOR_LOCK,
      ZCL_CLUSTER_ID_HVAC_PUMP_CONFIG_CONTROL,
      ZCL_CLUSTER_ID_HVAC_THERMOSTAT,
      ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT,
      ZCL_CLUSTER_ID_MS_ILLUMINANCE_MEASUREMENT,
      ZCL_CLUSTER_ID_MS_ILLUMINANCE_LEVEL_SENSING_CONFIG,
      ZCL_CLUSTER_ID_MS_PRESSURE_MEASUREMENT,
      ZCL_CLUSTER_ID_MS_FLOW_MEASUREMENT,
      ZCL_CLUSTER_ID_MS_RELATIVE_HUMIDITY,
      ZCL_CLUSTER_ID_MS_OCCUPANCY_SENSING,
      ZCL_CLUSTER_ID_SS_IAS_ZONE,
      ZCL_CLUSTER_ID_PI_ANALOG_INPUT_BACNET_REG,
      ZCL_CLUSTER_ID_PI_ANALOG_INPUT_BACNET_EXT,
      ZCL_CLUSTER_ID_PI_ANALOG_OUTPUT_BACNET_REG,
      ZCL_CLUSTER_ID_PI_ANALOG_OUTPUT_BACNET_EXT,
      ZCL_CLUSTER_ID_PI_ANALOG_VALUE_BACNET_REG,
      ZCL_CLUSTER_ID_PI_ANALOG_VALUE_BACNET_EXT,
      ZCL_CLUSTER_ID_PI_BINARY_INPUT_BACNET_REG,
      ZCL_CLUSTER_ID_PI_BINARY_INPUT_BACNET_EXT,
      ZCL_CLUSTER_ID_PI_BINARY_OUTPUT_BACNET_REG,
      ZCL_CLUSTER_ID_PI_BINARY_OUTPUT_BACNET_EXT,
      ZCL_CLUSTER_ID_PI_BINARY_VALUE_BACNET_REG,
      ZCL_CLUSTER_ID_PI_BINARY_VALUE_BACNET_EXT,
      ZCL_CLUSTER_ID_PI_MULTISTATE_INPUT_BACNET_REG,
      ZCL_CLUSTER_ID_PI_MULTISTATE_INPUT_BACNET_EXT,
      ZCL_CLUSTER_ID_PI_MULTISTATE_OUTPUT_BACNET_REG,
      ZCL_CLUSTER_ID_PI_MULTISTATE_OUTPUT_BACNET_EXT,
      ZCL_CLUSTER_ID_PI_MULTISTATE_VALUE_BACNET_REG,
      ZCL_CLUSTER_ID_PI_MULTISTATE_VALUE_BACNET_EXT,
      ZCL_CLUSTER_ID_SE_TUNNELING,
      ZCL_CLUSTER_ID_TELECOMMUNICATIONS_INFORMATION,
      ZCL_CLUSTER_ID_HA_APPLIANCE_IDENTIFICATION,
      ZCL_CLUSTER_ID_HA_METER_IDENTIFICATION,
      ZCL_CLUSTER_ID_HA_APPLIANCE_EVENTS_ALERTS,
      ZCL_CLUSTER_ID_HA_APPLIANCE_STATISTICS,
    };
    
    #ifdef ZCL_GROUPS
    static zclOptionRec_t zcl_Groups_Options[] =
    {
      {
        ZCL_CLUSTER_ID_GEN_GROUPS,
        ( AF_ACK_REQUEST ),
      },
    };
    #endif
    
    
     /*********************************************************************
     * LOCAL FUNCTIONS
     */
    static ZStatus_t bdb_zclFindingBindingAddBindEntry( byte SrcEndpInt,
                                      uint16 BindClusterId,
                                      byte Cnt,                 
                                      uint16 * ClusterList,
                                      zAddrType_t *DstAddr, byte DstEndpInt, uint8 addBind );
    
    uint8 bdb_FindIfAppCluster( cId_t ClusterId );
    
    
    static void bdb_zclSimpleDescClusterListClean( SimpleDescriptionFormat_t *pSimpleDesc );
    bdbFindingBindingRespondent_t* bdb_findRespondentNode(uint8 endpoint, uint16 shortAddress);
    bdbFindingBindingRespondent_t* bdb_getRespondentRetry(bdbFindingBindingRespondent_t* pRespondentHead);
    void bdb_checkMatchingEndpoints(uint8 bindIfMatch, uint16 shortAddress, bdbFindingBindingRespondent_t **pCurr);
     /*********************************************************************
     * PUBLIC FUNCTIONS
     *********************************************************************/
    
    void bdb_ProcessSimpleDesc( zdoIncomingMsg_t *msgPtr );
    void bdb_ProcessIEEEAddrRsp(zdoIncomingMsg_t *pMsg);
    
    /*********************************************************************
     * @fn      bdb_SetIdentifyActiveEndpoint
     *
     * @brief   Set the endpoint which will perform the finding and binding (either Target or Initiator)
     *
     * @param   Active endpoint with which perform F&B. If set to 0xFF all endpoints with Identify will be attempted.
     *
     * @return  ZFailure - F&B commissioning mode already requested
     *          ZInvalidParameter - Endpoint specified not found or reserved by Zigbee
     *          ZSuccess - 
     */
    ZStatus_t bdb_SetIdentifyActiveEndpoint(uint8 activeEndpoint)
    {
      epList_t *bdb_EpDescriptorListTemp = NULL;
      
      //Cannot process the request if no endpoints or F&B is under process
      if(bdbAttributes.bdbCommissioningMode & BDB_COMMISSIONING_MODE_FINDING_BINDING)
      {
        return ZFailure;
      }
      
      if(activeEndpoint == 0xFF)
      {
        bdbIndentifyActiveEndpoint = activeEndpoint;
        return ZSuccess;
      }
      
      if((activeEndpoint != 0) && (activeEndpoint < BDB_ZIGBEE_RESERVED_ENDPOINTS_START))
      {
        bdb_EpDescriptorListTemp = bdb_HeadEpDescriptorList;
        
        while(bdb_EpDescriptorListTemp != NULL)
        {
          if(bdb_EpDescriptorListTemp->epDesc->endPoint == activeEndpoint)
          {
            bdbIndentifyActiveEndpoint = activeEndpoint;
            return ZSuccess;
          }
          bdb_EpDescriptorListTemp = bdb_EpDescriptorListTemp->nextDesc;
        }
      }
      
      return ZInvalidParameter;
    }
    
    
    /*********************************************************************
     * @fn      bdb_setEpDescListToActiveEndpoint
     *
     * @brief   Set the endpoint list to the active endpoint selected by the application for F&B process
     *
     * @return  Current endpoint descriptor
     */
    
    endPointDesc_t* bdb_setEpDescListToActiveEndpoint(void)
    {
      bdb_CurrEpDescriptorList = bdb_HeadEpDescriptorList;
     
      //Check which active endpoit is being requested
      if(bdbIndentifyActiveEndpoint != 0xFF)
      {
        //Search for an specific endpoint
        while(bdb_CurrEpDescriptorList != NULL)
        {
          if(bdb_CurrEpDescriptorList->epDesc->endPoint == bdbIndentifyActiveEndpoint)
          {
            return bdb_CurrEpDescriptorList->epDesc;
          }
          bdb_CurrEpDescriptorList = bdb_CurrEpDescriptorList->nextDesc;
        }
      }
      else
      {
        //Look for the first endpoint that has Identify cluster
        while(bdb_CurrEpDescriptorList != NULL)
        {
          if((bdb_CurrEpDescriptorList->epDesc->endPoint != 0) && (bdb_CurrEpDescriptorList->epDesc->endPoint < BDB_ZIGBEE_RESERVED_ENDPOINTS_START))
          {
            return bdb_CurrEpDescriptorList->epDesc;
          }
          bdb_CurrEpDescriptorList = bdb_CurrEpDescriptorList->nextDesc;
        }
      }
      //not found
      return NULL;
    }
    
    
    /*********************************************************************
     * @fn      bdb_ProcessIEEEAddrRsp
     *
     * @brief   Process IEEE addr response and mark the entry as done or remove the 
     *          bind if not successful.
     *
     * @param   zdoIncomingMsg_t *pMsg
     *
     * @return  none
     */
    void bdb_ProcessIEEEAddrRsp(zdoIncomingMsg_t *pMsg)
    {
      ZDO_NwkIEEEAddrResp_t *pAddrRsp = NULL;
      bdbFindingBindingRespondent_t *pCurr = NULL;
    
      pAddrRsp = ZDO_ParseAddrRsp( pMsg );
      
      if(pAddrRsp == NULL)
      {
        return;
      }
      
      bdb_setEpDescListToActiveEndpoint();
      
      pCurr = bdb_findRespondentNode(bdb_FindingBindingTargetSimpleDesc.EndPoint, pAddrRsp->nwkAddr);
      
      //Does the entry exist and we were waiting an IEEE addr rsp from this device?
      if((pCurr != NULL) && (pCurr->attempts > FINDING_AND_BINDING_MISSING_IEEE_ADDR))
      {
        if(pAddrRsp->status == ZSuccess )
        {
          uint8 extAddr[8]; 
          AddrMgrEntry_t entry;
          
          entry.nwkAddr = pAddrRsp->nwkAddr;
          entry.user = ADDRMGR_USER_BINDING;
          AddrMgrExtAddrSet(entry.extAddr, pAddrRsp->extAddr);
          
          //Add it as bind entry
          if(AddrMgrEntryUpdate(&entry) == FALSE)
          {
            //No space, then report F&B table full
            //If periodic was triggered, then finish it
            if(FINDING_AND_BINDING_PERIODIC_ENABLE == TRUE)                                  
            {
              bdb_FB_InitiatorCurrentCyclesNumber = 0;
              osal_stop_timerEx(bdb_TaskID, BDB_FINDING_AND_BINDING_PERIOD_TIMEOUT);
            }
            
            bdb_zclSimpleDescClusterListClean( &bdb_FindingBindingTargetSimpleDesc );
            osal_stop_timerEx( bdb_TaskID, BDB_RESPONDENT_PROCESS_TIMEOUT );
            bdb_exitFindingBindingWStatus( BDB_COMMISSIONING_FB_BINDING_TABLE_FULL );
            return;
          }
    
          //search for the matching clusters to be added this time as we have the IEEE addrs
          bdb_checkMatchingEndpoints(TRUE, pAddrRsp->nwkAddr, &pCurr);
          (void)extAddr;  //dummy
        }
        //Bind cannot be added if the device was not found
        pCurr->attempts = FINDING_AND_BINDING_RESPONDENT_COMPLETE;
      }
      
      //release the memory
      osal_mem_free( pAddrRsp );
    }
    
    
    /*********************************************************************
     * @fn      bdb_StopInitiatorFindingBinding
     *
     * @brief   Stops finding and binding for initiator devices.
     *
     * @param   none
     *
     * @return  none
     */
    void bdb_StopInitiatorFindingBinding(void)
    {
      //If periodic was triggered, then finish it
      if(FINDING_AND_BINDING_PERIODIC_ENABLE == TRUE)                                  
      {
        bdb_FB_InitiatorCurrentCyclesNumber = 0;
        osal_stop_timerEx(bdb_TaskID, BDB_FINDING_AND_BINDING_PERIOD_TIMEOUT);
      }      
      //Clean the respondent list and stop its timer
      bdb_zclRespondentListClean( &pRespondentHead );
      osal_stop_timerEx( bdb_TaskID, BDB_RESPONDENT_PROCESS_TIMEOUT );
      
      //Notify status
      bdb_exitFindingBindingWStatus( BDB_COMMISSIONING_FB_NO_IDENTIFY_QUERY_RESPONSE );
    
    }
    
    
    /*********************************************************************
     * @fn      bdb_checkMatchingEndpoints
     *
     * @brief   Check active endpoints for F&B and the respondant simple descriptor 
     *          for matching application clusters
     *
     * @param   pRespondant - Respondant to be process
     * @param   bindIfMatch - Flag to indicate that binds for matching cluster must 
     *                        be done
     *
     * @return  status - Result of the operation
     */
    void bdb_checkMatchingEndpoints(uint8 bindIfMatch, uint16 shortAddr, bdbFindingBindingRespondent_t **pCurr)
    {
      uint8 matchFound;
      endPointDesc_t *bdb_CurrEpDescriptor;
      uint8 i, status;
      zAddrType_t dstAddr;
    #ifdef ZCL_GROUPS
      afAddrType_t afDstAddr;
    #endif  
      
      //Check all the endpoints active for F&B
      while(bdb_CurrEpDescriptorList != NULL)
      {
        matchFound = FALSE;
    
        bdb_CurrEpDescriptor = bdb_CurrEpDescriptorList->epDesc;
    
    #ifdef ZCL_GROUPS
        if ( bdbAttributes.bdbCommissioningGroupID != 0xFFFF )    
        {
          zcl_registerClusterOptionList(bdb_CurrEpDescriptor->endPoint,1,zcl_Groups_Options);      
          
          dstAddr.addr.shortAddr = bdbAttributes.bdbCommissioningGroupID;
          dstAddr.addrMode = AddrGroup;
        }
        else
    #endif
        {
          dstAddr.addrMode = Addr64Bit;
          if(bindIfMatch)
          {
            //if bind is to be created, then we should have the ext address in addr mgr
            AddrMgrExtAddrLookup( shortAddr, dstAddr.addr.extAddr );
          }
        }
        for(i = 0; i < bdb_CurrEpDescriptor->simpleDesc->AppNumOutClusters; i++)
        {
          //Filter for Application clusters (to bind app clusters only)
          status = bdb_zclFindingBindingAddBindEntry( bdb_CurrEpDescriptor->endPoint,
                                  bdb_CurrEpDescriptor->simpleDesc->pAppOutClusterList[i],
                                  bdb_FindingBindingTargetSimpleDesc.AppNumInClusters,
                                  bdb_FindingBindingTargetSimpleDesc.pAppInClusterList,
                                  &dstAddr, bdb_FindingBindingTargetSimpleDesc.EndPoint, bindIfMatch );
          
          if ( status == ZApsTableFull )
          {
            break;
          }
          else if(status == ZSuccess)
          {
            matchFound = TRUE;
            //If a match is found and we are not adding due to lack of IEEE addrs, then skip looking
            if(!bindIfMatch)
            {
              break;
            }
          }
        }
        
        //Only search for other matches if the table is not full and we have not 
        //found any match or we have to add bind as many as we can
        if( (status != ZApsTableFull) && (!matchFound || bindIfMatch) )      
        {
          for(i = 0; i < bdb_CurrEpDescriptor->simpleDesc->AppNumInClusters; i++)
          {
            //Filter for Application clusters (to bind app clusters only)
            status = bdb_zclFindingBindingAddBindEntry( bdb_CurrEpDescriptor->endPoint,
                                    bdb_CurrEpDescriptor->simpleDesc->pAppInClusterList[i],
                                    bdb_FindingBindingTargetSimpleDesc.AppNumOutClusters,
                                    bdb_FindingBindingTargetSimpleDesc.pAppOutClusterList,
                                    &dstAddr, bdb_FindingBindingTargetSimpleDesc.EndPoint, bindIfMatch );
    
            if ( status == ZApsTableFull )
            {
              break;
            }
            else if(status == ZSuccess)
            {
              matchFound = TRUE;
              
              //If a match is found and we are not adding due to lack of IEEE addrs, then skip looking
              if(!bindIfMatch)
              {
                break;
              }
            }
          }
        }
        
        //Check if we have found any match
        if( matchFound == TRUE )
        {
          if(bindIfMatch)
          {
            //Mark respondent as complete as simple desc has been process and we do 
            //have IEEE addrs
            (*pCurr)->attempts = FINDING_AND_BINDING_RESPONDENT_COMPLETE;
          }
          else
          {
            //Mark as we need IEEE addrs
            (*pCurr)->attempts = FINDING_AND_BINDING_MISSING_IEEE_ADDR;
          }
    
    #ifdef ZCL_GROUPS
          if ( bdbAttributes.bdbCommissioningGroupID != 0xFFFF )
          {
            afDstAddr.addr.shortAddr = shortAddr;
            afDstAddr.addrMode = afAddr16Bit;
            afDstAddr.endPoint = bdb_FindingBindingTargetSimpleDesc.EndPoint;
                
            zclGeneral_SendAddGroupRequest( bdb_CurrEpDescriptor->endPoint, &afDstAddr,
                                        COMMAND_GROUP_ADD, bdbAttributes.bdbCommissioningGroupID, grpName,
                                        TRUE, 0x00 );
          }
    #endif
        }
        else
        {
          //No matching cluster, then we are done with this respondent
          (*pCurr)->attempts = FINDING_AND_BINDING_RESPONDENT_COMPLETE;
        }
        
        if ( status == ZApsTableFull )
        {
          //If periodic was triggered, then finish it
          if(FINDING_AND_BINDING_PERIODIC_ENABLE == TRUE)                                  
          {
            bdb_FB_InitiatorCurrentCyclesNumber = 0;
            osal_stop_timerEx(bdb_TaskID, BDB_FINDING_AND_BINDING_PERIOD_TIMEOUT);
          }      
          
          bdb_zclSimpleDescClusterListClean( &bdb_FindingBindingTargetSimpleDesc );
          osal_stop_timerEx( bdb_TaskID, BDB_RESPONDENT_PROCESS_TIMEOUT );
          bdb_exitFindingBindingWStatus( BDB_COMMISSIONING_FB_BINDING_TABLE_FULL );
          
          return;
        }
        
        //If an specific endpoint was requested, then don't go trough the rest of 
        //the endpoints
        if( bdbIndentifyActiveEndpoint != 0xFF )
        {
          break;
        }
        else
        {
          //If active endpoints 'all' is attempted, then process the next endpoint in 
          //the list
          bdb_CurrEpDescriptorList = bdb_CurrEpDescriptorList->nextDesc;
    
          while(bdb_CurrEpDescriptorList != NULL)
          {
            //It has to be different from 0 or reserved for Zigbee
            if((bdb_CurrEpDescriptorList->epDesc->endPoint != 0) && (bdb_CurrEpDescriptorList->epDesc->endPoint < BDB_ZIGBEE_RESERVED_ENDPOINTS_START))
            {
              break;
            }
            bdb_CurrEpDescriptorList = bdb_CurrEpDescriptorList->nextDesc;
          }
        }
      }
    }
    
    
    
    /*********************************************************************
     * @fn      bdb_ProcessSimpleDesc
     *
     * @brief   Process simple descriptor requested by F&B. Binds will be added if 
     *          matching cluster is found and if IEEE addrs of the device is already 
     *          stored
     *
     * @param   msgPtr - pointer to simple descriptor response indication message
     *
     * @return  none
     */
    void bdb_ProcessSimpleDesc( zdoIncomingMsg_t *msgPtr )
    {
      zAddrType_t dstAddr;
      bdbFindingBindingRespondent_t *pCurr = NULL;
      uint8 isRespondantReadyToBeAdded = FALSE;
    
      bdb_setEpDescListToActiveEndpoint();
      
      if ( !(bdb_CurrEpDescriptorList->epDesc->epType & BDB_FINDING_AND_BINDING_INITIATOR )) 
      {  
        //We should not be processing these commands as we are not initiator
        return;
      }
      
      dstAddr.addr.shortAddr = BUILD_UINT16( msgPtr->asdu[1], msgPtr->asdu[2] );
      dstAddr.addrMode = Addr16Bit;
      
      ZDO_ParseSimpleDescBuf( &msgPtr->asdu[4], &bdb_FindingBindingTargetSimpleDesc );
      
      pCurr = bdb_findRespondentNode(bdb_FindingBindingTargetSimpleDesc.EndPoint, dstAddr.addr.shortAddr);
      
      //Just for safety check this is a valid entry
      if(pCurr != NULL) 
      {
        uint8 extAddr[Z_EXTADDR_LEN]; 
        
        if(AddrMgrExtAddrLookup( pCurr->data.addr.shortAddr, extAddr ))
        {
          isRespondantReadyToBeAdded = TRUE;
        }
        else
        {
          //Save the simple desc to don't ask for it again
          pCurr->SimpleDescriptor = &bdb_FindingBindingTargetSimpleDesc;
        }
        (void)extAddr;  //dummy
      }
      else
      {
        //This simple desc rsp was not requested by BDB F&B
        return;
      } 
      
      bdb_checkMatchingEndpoints(isRespondantReadyToBeAdded, dstAddr.addr.shortAddr, &pCurr);
      
      //If the respondent got process complete, then release the entry
      if(pCurr->attempts == FINDING_AND_BINDING_RESPONDENT_COMPLETE)
      {
        bdb_zclSimpleDescClusterListClean( &bdb_FindingBindingTargetSimpleDesc );  
      }
    }
    
    /*********************************************************************
     * @fn      bdb_zclFindingBindingEpType
     *
     * @brief   Gives the Ep Type according to application clusters in
     *          simple descriptor
     *
     * @return  epType - If Target, Initiator or both
     */
    uint8 bdb_zclFindingBindingEpType( endPointDesc_t *epDesc )
    {
      uint8 epType = 0;
      uint8 status;
      uint8 type1ClusterCnt;
      uint8 type2ClusterCnt;
      
      type1ClusterCnt = sizeof( bdb_ZclType1Clusters )/sizeof( uint16 );
      type2ClusterCnt = sizeof( bdb_ZclType2Clusters )/sizeof( uint16 );
      
    
      // Are there matching type 1 on server side?
      status = ZDO_AnyClusterMatches( epDesc->simpleDesc->AppNumInClusters, 
                                      epDesc->simpleDesc->pAppInClusterList,
                                      type1ClusterCnt,
                                      (uint16*)bdb_ZclType1Clusters);
      
      if( status == TRUE )
      {
        epType |= BDB_FINDING_AND_BINDING_TARGET;
      }
      
      // Are there matching type 1 on client side?
      status = ZDO_AnyClusterMatches( epDesc->simpleDesc->AppNumOutClusters, 
                                      epDesc->simpleDesc->pAppOutClusterList,
                                      type1ClusterCnt,
                                      (uint16*)bdb_ZclType1Clusters);
      
      if( status == TRUE )
      {
        epType |= BDB_FINDING_AND_BINDING_INITIATOR;
      }
      
      // Are there matching type 2 on server side?
      status = ZDO_AnyClusterMatches( epDesc->simpleDesc->AppNumInClusters, 
                                      epDesc->simpleDesc->pAppInClusterList,
                                      type2ClusterCnt,
                                      (uint16*)bdb_ZclType2Clusters);
      
      if( status == TRUE )
      {
        epType |= BDB_FINDING_AND_BINDING_INITIATOR;
      }
      
      // Are there matching type 2 on client side?
      status = ZDO_AnyClusterMatches( epDesc->simpleDesc->AppNumOutClusters, 
                                      epDesc->simpleDesc->pAppOutClusterList,
                                      type2ClusterCnt,
                                      (uint16*)bdb_ZclType2Clusters);
      
      if( status == TRUE )
      {
        epType |= BDB_FINDING_AND_BINDING_TARGET;
      }
    
      return epType;
    
    }
    
    /*********************************************************************
     * @fn      bdb_zclFindingBindingAddBindEntry
     *
     * @brief   This function is used to Add an entry to the binding table
     *
     * @param   SrcEndpInt - source endpoint
     * @param   BindClusterId - cluster to try bind
     * @param   Cnt - list of remote clusters
     * @param   ClusterList - pointer to the Object ID list
     * @param   DstAddr - Address of remote node
     * @param   DstEndpInt - EndPoint of remote node
     * @param   addBind - Indicate wheter or not bind must be added or not
     *
     * @return  status - Success if added
     */
    static ZStatus_t bdb_zclFindingBindingAddBindEntry( byte SrcEndpInt,
                                      uint16 BindClusterId,
                                      byte Cnt,                 
                                      uint16 * ClusterList,
                                      zAddrType_t *DstAddr, byte DstEndpInt, uint8 addBind )
    {
      uint8 status;
    
      if ( bdb_FindIfAppCluster ( BindClusterId ) != SUCCESS )
      {
        return ( ZApsFail ); // No App cluster
      }
    
      // Are there matching clusters?
      status = ZDO_AnyClusterMatches( Cnt, 
                                      ClusterList,
                                      1,
                                     &BindClusterId);
      if ( status == FALSE )
      {
        return ( ZApsFail ); // No matched Cluster
      }
    
      if(addBind)  
      {
        if ( pbindAddEntry )
        {
          // Add the entry into the binding table
          if (!pbindAddEntry( SrcEndpInt, DstAddr, DstEndpInt,
                                 1, &BindClusterId ) )
          {
            return ( ZApsTableFull );
          }
        }
      }
      
      return ( ZSuccess );
    }
    
    /*********************************************************************
     * @fn      bdb_exitFindingBindingWStatus
     *
     * @brief   Clean respondent list and reports the status to bdb state machine
     *
     * @return  
     */
    void bdb_exitFindingBindingWStatus( uint8 status )
    {
      // bdb report status
      bdbAttributes.bdbCommissioningStatus = status;
      
      bdb_reportCommissioningState( BDB_COMMISSIONING_STATE_FINDING_BINDING, TRUE );
    }
    
    /*********************************************************************
     * @fn      bdb_zclSimpleDescClusterListClean
     *
     * @brief   This function free Simple Descriptor cluster lists
     *
     * @param   pSimpleDesc - pointer to simple descriptor
     *
     * @return  status
     */
    static void bdb_zclSimpleDescClusterListClean( SimpleDescriptionFormat_t *pSimpleDesc )
    {
      if(pSimpleDesc->pAppInClusterList != NULL)
      {
        osal_mem_free( pSimpleDesc->pAppInClusterList );
        pSimpleDesc->pAppInClusterList = ( cId_t* )NULL;
      }
      if(pSimpleDesc->pAppOutClusterList != NULL)
      {
        osal_mem_free( pSimpleDesc->pAppOutClusterList );
        pSimpleDesc->pAppOutClusterList = ( cId_t* )NULL;
      }
    }
    
    /*********************************************************************
     * @fn      bdb_RegisterIdentifyTimeChangeCB
     *
     * @brief   Register an Application's Identify Time change callback function
     *          to let know the application when identify is active or not.
     *
     * @param   pfnIdentify - application callback
     *
     * @return  none
     */
    void bdb_RegisterIdentifyTimeChangeCB( bdbGCB_IdentifyTimeChange_t pfnIdentifyTimeChange )
    {
      pfnIdentifyTimeChangeCB = pfnIdentifyTimeChange;
    }
    
    #if (FINDING_AND_BINDING_PERIODIC_ENABLE==TRUE)
    /*********************************************************************
     * @fn      bdb_GetFBInitiatorStatus
     *
     * @brief   Get the F&B initiator status for periodic requests.
     *
     * @param   RemainingTime - in seconds
     * @param   AttemptsLeft - number of attempts to be done
     * @param   MatchesFound - Add the number of matches to this parameter
     *                         since the last bdb_GetFBInitiatorStatus call
     *
     * @return  none
     */
    void bdb_GetFBInitiatorStatus(uint8 *RemainingTime, uint8* AttemptsLeft)
    {
      if(RemainingTime != NULL)  
      {
        if (bdb_FB_InitiatorCurrentCyclesNumber == 0)
        {
          *RemainingTime = 0;
        }
        else
        {
          *RemainingTime = (bdb_FB_InitiatorCurrentCyclesNumber - 1) * FINDING_AND_BINDING_PERIODIC_TIME + ((osal_get_timeoutEx(bdb_TaskID, BDB_FINDING_AND_BINDING_PERIOD_TIMEOUT) + 999) / 1000);
        }
      }
      
      if(AttemptsLeft != NULL)
      {
        *AttemptsLeft = bdb_FB_InitiatorCurrentCyclesNumber;
      }
    }
    #endif
    
    /*********************************************************************
     * @fn      bdb_RegisterBindNotificationCB
     *
     * @brief   Register an Application's notification callback function to let 
     *          know the application when a new bind is added to the binding table.
     *
     * @param   pfnIdentify - application callback
     *
     * @return  none
     */
    void bdb_RegisterBindNotificationCB( bdbGCB_BindNotification_t pfnBindNotification )
    {
      pfnBindNotificationCB = pfnBindNotification;
    }
    
    /*********************************************************************
     * @fn      bdb_SendIdentifyQuery
     *
     * @brief   Sends Identify query from the given endpoint
     *
     * @param   endpoint
     *
     * @return  ZStatus_t
     */
    ZStatus_t bdb_SendIdentifyQuery( uint8 endpoint )
    {
      afAddrType_t dstAddr;
      ZStatus_t    status;
      
      dstAddr.addr.shortAddr = NWK_BROADCAST_SHORTADDR_DEVALL;
      dstAddr.addrMode = afAddr16Bit;
      dstAddr.endPoint = 0xFF;
    
      status = zclGeneral_SendIdentifyQuery( endpoint, &dstAddr, TRUE, bdb_getZCLFrameCounter() ); 
      
      if(status == ZSuccess)
      {
        osal_start_timerEx( bdb_TaskID, BDB_RESPONDENT_PROCESS_TIMEOUT, IDENTIFY_QUERY_RSP_TIMEOUT );
      }
      
      return status;
    }
    
    /*********************************************************************
     * @fn      bdb_ZclIdentifyQueryCmdInd
     *
     * @brief   Callback from the ZCL General Cluster Library when
     *          it received an Identity Query Response Command for this 
     *          application.
     *
     * @param   srcAddr - source address and endpoint of the response message
     * @param   identifyTime - the number of seconds to identify yourself
     *
     * @return  none
     */
    void bdb_ZclIdentifyQueryCmdInd( zclIdentifyQueryRsp_t *pCmd )
    {
      bdbFindingBindingRespondent_t *pCurr;
      
      // Stop the timer before refresh
      osal_stop_timerEx( bdb_TaskID, BDB_RESPONDENT_PROCESS_TIMEOUT );
      
      // add new node to the list
      pCurr = bdb_AddRespondentNode( &pRespondentHead, pCmd );
      
      if(pCurr != NULL)
      {
        pCurr->data.addrMode = pCmd->srcAddr->addrMode;
        pCurr->data.addr.shortAddr = pCmd->srcAddr->addr.shortAddr;
        pCurr->data.endPoint = pCmd->srcAddr->endPoint;
        pCurr->data.panId = pCmd->srcAddr->panId;
        pCurr->attempts = FINDING_AND_BINDING_NEW_RESPONDENT;
        pCurr->SimpleDescriptor = NULL;
      }
      
      //Process the identify query rsp
      osal_set_event(bdb_TaskID, BDB_RESPONDENT_PROCESS_TIMEOUT);
    }
    
    /*********************************************************************
     * @fn      bdb_ProcessRespondentList
     *
     * @brief   Process the respondent list by sending Simple Descriptor request to 
     *          devices respondent in the list. Also send IEEE Addr Req to those 
     *          device for which a bind is created buy IEEE addr is missing.
     *
     * @param   none
     *
     * @return  none
     */
    void bdb_ProcessRespondentList( void )
    {
      zAddrType_t dstAddr = { 0 };
      
      // Look for the first respondent
      if ( pRespondentCurr == NULL )
      {
        pRespondentCurr = bdb_getRespondentRetry(pRespondentHead);
        
        // If null, then no responses from Identify query request
        if ( (pRespondentCurr == NULL) )
        {
          //No responses, then no responses
          if(pRespondentHead == NULL)
          {
            bdb_exitFindingBindingWStatus( BDB_COMMISSIONING_FB_NO_IDENTIFY_QUERY_RESPONSE );
          }
          //Responses and binded to all clusters possible
          else
          {
            bdb_exitFindingBindingWStatus( BDB_COMMISSIONING_SUCCESS );
          }
          return;
        }
      }
      else
      {
        //Validate that we are not processing a missing IEEE Address before chaning 
        //the current respondent to be process
        if((pRespondentCurr->attempts & FINDING_AND_BINDING_MISSING_IEEE_ADDR) &&
           (pRespondentCurr->attempts & ~FINDING_AND_BINDING_MISSING_IEEE_ADDR) >= FINDING_AND_BINDING_MAX_ATTEMPTS)
        {
          if(pRespondentNext == NULL)
          {
            //Review the whole list if we have simple desc that we need to attempt.
            pRespondentCurr = bdb_getRespondentRetry(pRespondentHead);
              
            if(pRespondentCurr == NULL)
            {
              bdb_exitFindingBindingWStatus( BDB_COMMISSIONING_SUCCESS );
              return;
            }
          }
          else
          {
            pRespondentCurr = pRespondentNext;
          }
        }
      }
      
      //Start the timer to process the next respondent
      osal_start_timerEx( bdb_TaskID, BDB_RESPONDENT_PROCESS_TIMEOUT, SIMPLEDESC_RESPONSE_TIMEOUT );
      
      //If ParentLost is reported, then do not attempt send SimpleDesc, mark those as pending, 
      //if Parent Lost is restored, then these simpleDesc attempts will be restored to 0
      if(bdbCommissioningProcedureState.bdbCommissioningState != BDB_PARENT_LOST)
      {
        dstAddr.addr.shortAddr = pRespondentCurr->data.addr.shortAddr;
        dstAddr.addrMode = pRespondentCurr->data.addrMode;
    
        //Update the attempts, ahead of actually sending the frame, as this is done just below
        pRespondentCurr->attempts++;
        
        //Send IEEE addr request or simple desc req
        if(pRespondentCurr->attempts & FINDING_AND_BINDING_MISSING_IEEE_ADDR)
        {
          ZDP_IEEEAddrReq(pRespondentCurr->data.addr.shortAddr,0,0,0);
        }
        else
        {
          //Send simple descriptor
          ZDP_SimpleDescReq( &dstAddr, pRespondentCurr->data.addr.shortAddr, pRespondentCurr->data.endPoint, 0 );
        }
      }
      else
      {
        //Stop any attempt due to parent lost
        pRespondentCurr->attempts |= FINDING_AND_BINDING_PARENT_LOST;
      }
      
      //Search for the next respondant that has not enough tries in the list
      pRespondentNext = bdb_getRespondentRetry(pRespondentCurr->pNext);
    }
    
    /*********************************************************************
     * @fn      bdb_FindIfAppCluster
     *
     * @brief   To verify if cluster is application type
     *
     * @param   none
     *
     * @return  true if success
     */
    uint8 bdb_FindIfAppCluster( cId_t ClusterId )
    {
      uint8 i;
      uint8 ClusterCnt;
    
      ClusterCnt = sizeof( bdb_ZclType1Clusters )/sizeof( uint16 );
      
      for ( i = 0; i < ClusterCnt; i++ )
      {
        if ( bdb_ZclType1Clusters[i] == ClusterId )
        {
          return ( SUCCESS );
        }
      }
      
      ClusterCnt = sizeof( bdb_ZclType2Clusters )/sizeof( uint16 );
      
      for ( i = 0; i < ClusterCnt; i++ )
      {
        if ( bdb_ZclType2Clusters[i] == ClusterId )
        {
          return ( SUCCESS );
        }
      }
      
      // If not found, take it as application cluster it will be filtered
      // by simple descriptor at some point
      return ( FAILURE );
    }
    
    
    /*********************************************************************
     * @fn      bdb_getRespondentRetry
     *
     * @brief   Get the next Respondant entry to retry
     *
     * @param   pHead - pointer to a pointer of the list head
     *
     * @return  respondant entry if found, otherwise NULL
     */
    bdbFindingBindingRespondent_t* bdb_getRespondentRetry(bdbFindingBindingRespondent_t* pRespondentHead)
    {
      bdbFindingBindingRespondent_t *pTemp;
      
      pTemp = pRespondentHead;
      
      while(pTemp != NULL)
      {
        //does the next entry requires to perform an attempt on simple desc req or IEEE addr req?
        if((pTemp->attempts & ~FINDING_AND_BINDING_MISSING_IEEE_ADDR) < FINDING_AND_BINDING_MAX_ATTEMPTS)
        {
          return pTemp;
        }
       
        pTemp = pTemp->pNext;
      }
      return NULL;
    }
    
    
    bdbFindingBindingRespondent_t* bdb_findRespondentNode(uint8 endpoint, uint16 shortAddress)
    {
      bdbFindingBindingRespondent_t* pTemp = pRespondentHead;
      
      while(pTemp != NULL)  
      {
        if((pTemp->data.addr.shortAddr == shortAddress) && (pTemp->data.endPoint == endpoint))
        {
          return pTemp;
        }
        
        pTemp = pTemp->pNext;
      }
      
      return NULL;
    }
    
    #endif  
    
    /*********************************************************************
    *********************************************************************/