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: Setup procedure for Coord and ED using Z-Stack 3.0.1 and data exchange b/w Coord and ED

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

Hello everyone,

I have recently purchased four CC2530 (https://www.waveshare.com/wiki/Core2530basics. Using the GenericApp sample application and the instructions given in documents i'm able to setup a coordinator and end device. However, I'm unable to setup a data link between the end device and coordinator and i don't understand the basic setup procedure given in other examples. 

Request you expert advice to get my project going.

  • Are you sure your device joins coordinator? And, how do you send message between device and coordinator?
  • Yes, the end device joins the coordinator. Please see below the screenshot of ubiqua protocol analyzer for reference. You can find the end device joins coordinator.

    I planning to send a temperature data in a unsigned integer format to the coordinator at an periodic interval of 15 minutes.

  • Can you please post the *.cubx file? Also, you probably need to enter this key as a Trust Center Link Key in the Ubiqua Key Chain:

    5a 69 67 62 65 65 41 6c 6c 69 61 6e 63 65 30 39
  • If you intend to send temperature data, I suggest you to use SampleTemperatureSensor and SampleTheomostate example.
  • Thank you Jason. Let me add Trust Center Link key and capture the cubx file and post it soon.
  • You can attach your cubx file of the screenshot.
  • Yes, the device 0x3315 joins coordinator correctly. I see the device sends a proprietary message to coordinator on Packet number 38. Is that packe sent by you?
  • No, I'm not sending any message to coordinator.

    Let me share some additional information on the setup i have in my lab. I use ZB502 () development board for my experiment. For software, i use  GenericApp example code from Z-Stack samples. To handle Key1 press i modified hal_key.c (to capture Key1 press) and zcl_genericapp.c (to run commissioning procedure on Key1 press). There is no update made on other files. My goal is first make the End Device to find Coordinator (which i'm able to do so). Next i want to start add logic to send temperature sensor detail to the coordinator at an regular interval.

    Note: Attached the hal_key and zcl_genericapp for your view.

    /**************************************************************************************************
      Filename:       hal_key.c
      Revised:        $Date: 2010-09-15 19:02:45 -0700 (Wed, 15 Sep 2010) $
      Revision:       $Revision: 23815 $
    
      Description:    This file contains the interface to the HAL KEY Service.
    
    
      Copyright 2006-2010 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.
    **************************************************************************************************/
    /*********************************************************************
     NOTE: If polling is used, the hal_driver task schedules the KeyRead()
           to occur every 100ms.  This should be long enough to naturally
           debounce the keys.  The KeyRead() function remembers the key
           state of the previous poll and will only return a non-zero
           value if the key state changes.
    
     NOTE: If interrupts are used, the KeyRead() function is scheduled
           25ms after the interrupt occurs by the ISR.  This delay is used
           for key debouncing.  The ISR disables any further Key interrupt
           until KeyRead() is executed.  KeyRead() will re-enable Key
           interrupts after executing.  Unlike polling, when interrupts
           are enabled, the previous key state is not remembered.  This
           means that KeyRead() will return the current state of the keys
           (not a change in state of the keys).
    
     NOTE: If interrupts are used, the KeyRead() fucntion is scheduled by
           the ISR.  Therefore, the joystick movements will only be detected
           during a pushbutton interrupt caused by S1 or the center joystick
           pushbutton.
    
     NOTE: When a switch like S1 is pushed, the S1 signal goes from a normally
           high state to a low state.  This transition is typically clean.  The
           duration of the low state is around 200ms.  When the signal returns
           to the high state, there is a high likelihood of signal bounce, which
           causes a unwanted interrupts.  Normally, we would set the interrupt
           edge to falling edge to generate an interrupt when S1 is pushed, but
           because of the signal bounce, it is better to set the edge to rising
           edge to generate an interrupt when S1 is released.  The debounce logic
           can then filter out the signal bounce.  The result is that we typically
           get only 1 interrupt per button push.  This mechanism is not totally
           foolproof because occasionally, signal bound occurs during the falling
           edge as well.  A similar mechanism is used to handle the joystick
           pushbutton on the DB.  For the EB, we do not have independent control
           of the interrupt edge for the S1 and center joystick pushbutton.  As
           a result, only one or the other pushbuttons work reasonably well with
           interrupts.  The default is the make the S1 switch on the EB work more
           reliably.
    
    *********************************************************************/
    
    /**************************************************************************************************
     *                                            INCLUDES
     **************************************************************************************************/
    #include "hal_mcu.h"
    #include "hal_defs.h"
    #include "hal_types.h"
    #include "hal_board.h"
    #include "hal_drivers.h"
    #include "hal_adc.h"
    #include "hal_key.h"
    #include "osal.h"
    
    #if (defined HAL_KEY) && (HAL_KEY == TRUE)
    
    /**************************************************************************************************
     *                                              MACROS
     **************************************************************************************************/
    
    /**************************************************************************************************
     *                                            CONSTANTS
     **************************************************************************************************/
    #define HAL_KEY_RISING_EDGE   0
    #define HAL_KEY_FALLING_EDGE  1
    
    #define HAL_KEY_DEBOUNCE_VALUE  25
    
    /* CPU port interrupt */
    #define HAL_KEY_CPU_PORT_0_IF P0IF
    #define HAL_KEY_CPU_PORT_2_IF P2IF
    
    /* SW_6 is at P0.1 */
    #define HAL_KEY_SW_6_PORT   P0
    #define HAL_KEY_SW_6_BIT    BV(1)
    #define HAL_KEY_SW_6_SEL    P0SEL
    #define HAL_KEY_SW_6_DIR    P0DIR
    
    /* edge interrupt */
    #define HAL_KEY_SW_6_EDGEBIT  BV(0)
    #define HAL_KEY_SW_6_EDGE     HAL_KEY_FALLING_EDGE
    
    
    /* SW_6 interrupts */
    #define HAL_KEY_SW_6_IEN      IEN1  /* CPU interrupt mask register */
    #define HAL_KEY_SW_6_IENBIT   BV(5) /* Mask bit for all of Port_0 */
    #define HAL_KEY_SW_6_ICTL     P0IEN /* Port Interrupt Control register */
    #define HAL_KEY_SW_6_ICTLBIT  BV(1) /* P0IEN - P0.1 enable/disable bit */
    #define HAL_KEY_SW_6_PXIFG    P0IFG /* Interrupt flag at source */
    
    /* Joy stick move at P2.0 */
    #define HAL_KEY_JOY_MOVE_PORT   P2
    #define HAL_KEY_JOY_MOVE_BIT    BV(0)
    #define HAL_KEY_JOY_MOVE_SEL    P2SEL
    #define HAL_KEY_JOY_MOVE_DIR    P2DIR
    
    /* edge interrupt */
    #define HAL_KEY_JOY_MOVE_EDGEBIT  BV(3)
    #define HAL_KEY_JOY_MOVE_EDGE     HAL_KEY_FALLING_EDGE
    
    /* Joy move interrupts */
    #define HAL_KEY_JOY_MOVE_IEN      IEN2  /* CPU interrupt mask register */
    #define HAL_KEY_JOY_MOVE_IENBIT   BV(1) /* Mask bit for all of Port_2 */
    #define HAL_KEY_JOY_MOVE_ICTL     P2IEN /* Port Interrupt Control register */
    #define HAL_KEY_JOY_MOVE_ICTLBIT  BV(0) /* P2IENL - P2.0<->P2.3 enable/disable bit */
    #define HAL_KEY_JOY_MOVE_PXIFG    P2IFG /* Interrupt flag at source */
    
    #define HAL_KEY_JOY_CHN   HAL_ADC_CHANNEL_6
    
    
    /**************************************************************************************************
     *                                            TYPEDEFS
     **************************************************************************************************/
    
    
    /**************************************************************************************************
     *                                        GLOBAL VARIABLES
     **************************************************************************************************/
    static uint8 halKeySavedKeys;     /* used to store previous key state in polling mode */
    static halKeyCBack_t pHalKeyProcessFunction;
    static uint8 HalKeyConfigured;
    bool Hal_KeyIntEnable;            /* interrupt enable/disable flag */
    
    /**************************************************************************************************
     *                                        FUNCTIONS - Local
     **************************************************************************************************/
    void halProcessKeyInterrupt(void);
    uint8 halGetJoyKeyInput(void);
    
    
    
    /**************************************************************************************************
     *                                        FUNCTIONS - API
     **************************************************************************************************/
    
    
    /**************************************************************************************************
     * @fn      HalKeyInit
     *
     * @brief   Initilize Key Service
     *
     * @param   none
     *
     * @return  None
     **************************************************************************************************/
    void HalKeyInit( void )
    {
      /* Initialize previous key to 0 */
      halKeySavedKeys = 0;
    
      HAL_KEY_SW_6_SEL &= ~(HAL_KEY_SW_6_BIT);    /* Set pin function to GPIO */
    
    #if ! defined ENABLE_LED4_DISABLE_S1
      HAL_KEY_SW_6_DIR &= ~(HAL_KEY_SW_6_BIT);    /* Set pin direction to Input */
    #endif
    
      HAL_KEY_JOY_MOVE_SEL &= ~(HAL_KEY_JOY_MOVE_BIT); /* Set pin function to GPIO */
      HAL_KEY_JOY_MOVE_DIR &= ~(HAL_KEY_JOY_MOVE_BIT); /* Set pin direction to Input */
    
    
      /* Initialize callback function */
      pHalKeyProcessFunction  = NULL;
    
      /* Start with key is not configured */
      HalKeyConfigured = FALSE;
    }
    
    
    /**************************************************************************************************
     * @fn      HalKeyConfig
     *
     * @brief   Configure the Key serivce
     *
     * @param   interruptEnable - TRUE/FALSE, enable/disable interrupt
     *          cback - pointer to the CallBack function
     *
     * @return  None
     **************************************************************************************************/
    void HalKeyConfig (bool interruptEnable, halKeyCBack_t cback)
    {
      /* Enable/Disable Interrupt or */
      Hal_KeyIntEnable = interruptEnable;
    
      /* Register the callback fucntion */
      pHalKeyProcessFunction = cback;
    
      /* Determine if interrupt is enable or not */
      if (Hal_KeyIntEnable)
      {
        /* Rising/Falling edge configuratinn */
    
        PICTL &= ~(HAL_KEY_SW_6_EDGEBIT);    /* Clear the edge bit */
        /* For falling edge, the bit must be set. */
      #if (HAL_KEY_SW_6_EDGE == HAL_KEY_FALLING_EDGE)
        PICTL |= HAL_KEY_SW_6_EDGEBIT;
      #endif
    
    
        /* Interrupt configuration:
         * - Enable interrupt generation at the port
         * - Enable CPU interrupt
         * - Clear any pending interrupt
         */
        HAL_KEY_SW_6_ICTL |= HAL_KEY_SW_6_ICTLBIT;
        HAL_KEY_SW_6_IEN |= HAL_KEY_SW_6_IENBIT;
        HAL_KEY_SW_6_PXIFG = ~(HAL_KEY_SW_6_BIT);
    
    
    
        /* Rising/Falling edge configuratinn */
    
        HAL_KEY_JOY_MOVE_ICTL &= ~(HAL_KEY_JOY_MOVE_EDGEBIT);    /* Clear the edge bit */
        /* For falling edge, the bit must be set. */
      #if (HAL_KEY_JOY_MOVE_EDGE == HAL_KEY_FALLING_EDGE)
        HAL_KEY_JOY_MOVE_ICTL |= HAL_KEY_JOY_MOVE_EDGEBIT;
      #endif
    
    
        /* Interrupt configuration:
         * - Enable interrupt generation at the port
         * - Enable CPU interrupt
         * - Clear any pending interrupt
         */
        HAL_KEY_JOY_MOVE_ICTL |= HAL_KEY_JOY_MOVE_ICTLBIT;
        HAL_KEY_JOY_MOVE_IEN |= HAL_KEY_JOY_MOVE_IENBIT;
        HAL_KEY_JOY_MOVE_PXIFG = ~(HAL_KEY_JOY_MOVE_BIT);
    
    
        /* Do this only after the hal_key is configured - to work with sleep stuff */
        if (HalKeyConfigured == TRUE)
        {
          osal_stop_timerEx(Hal_TaskID, HAL_KEY_EVENT);  /* Cancel polling if active */
        }
      }
      else    /* Interrupts NOT enabled */
      {
        HAL_KEY_SW_6_ICTL &= ~(HAL_KEY_SW_6_ICTLBIT); /* don't generate interrupt */
        HAL_KEY_SW_6_IEN &= ~(HAL_KEY_SW_6_IENBIT);   /* Clear interrupt enable bit */
    
        osal_set_event(Hal_TaskID, HAL_KEY_EVENT);
      }
    
      /* Key now is configured */
      HalKeyConfigured = TRUE;
    }
    
    
    /**************************************************************************************************
     * @fn      HalKeyRead
     *
     * @brief   Read the current value of a key
     *
     * @param   None
     *
     * @return  keys - current keys status
     **************************************************************************************************/
    uint8 HalKeyRead ( void )
    {
      uint8 keys = 0;
    
      if (HAL_PUSH_BUTTON1())
      {
        keys |= HAL_KEY_SW_6;
      }
    
      if ((HAL_KEY_JOY_MOVE_PORT & HAL_KEY_JOY_MOVE_BIT))  /* Key is active low */
      {
        keys |= halGetJoyKeyInput();
      }
    
      return keys;
    }
    
    
    /**************************************************************************************************
     * @fn      HalKeyPoll
     *
     * @brief   Called by hal_driver to poll the keys
     *
     * @param   None
     *
     * @return  None
     **************************************************************************************************/
    void HalKeyPoll (void)
    {
      uint8 keys = 0;
    #if 0
      if ((HAL_KEY_JOY_MOVE_PORT & HAL_KEY_JOY_MOVE_BIT))  /* Key is active HIGH */
      {
        keys = halGetJoyKeyInput();
      }
    
      /* If interrupts are not enabled, previous key status and current key status
       * are compared to find out if a key has changed status.
       */
      if (!Hal_KeyIntEnable)
      {
        if (keys == halKeySavedKeys)
        {
          /* Exit - since no keys have changed */
          return;
        }
        /* Store the current keys for comparation next time */
        halKeySavedKeys = keys;
      }
      else
      {
        /* Key interrupt handled here */
      }
    #endif
      if (!HAL_PUSH_BUTTON1())
      {
        keys |= HAL_KEY_SW_6;
      }
    
      /* Invoke Callback if new keys were depressed */
      if (pHalKeyProcessFunction
    #ifdef HAL_LEGACY_KEYS
        && keys //in legacy modes, only report key presses and do not report when a key is released
    #endif
        )
      {
        (pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);
      }
    }
    
    /**************************************************************************************************
     * @fn      halGetJoyKeyInput
     *
     * @brief   Map the ADC value to its corresponding key.
     *
     * @param   None
     *
     * @return  keys - current joy key status
     **************************************************************************************************/
    uint8 halGetJoyKeyInput(void)
    {
      /* The joystick control is encoded as an analog voltage.
       * Read the JOY_LEVEL analog value and map it to joy movement.
       */
      uint8 adc;
      uint8 ksave0 = 0;
      uint8 ksave1;
    
      /* Keep on reading the ADC until two consecutive key decisions are the same. */
      do
      {
        ksave1 = ksave0;    /* save previouse key reading */
    
        adc = HalAdcRead (HAL_KEY_JOY_CHN, HAL_ADC_RESOLUTION_8);
    
        if ((adc >= 2) && (adc <= 38))
        {
           ksave0 |= HAL_KEY_UP;
        }
        else if ((adc >= 74) && (adc <= 88))
        {
          ksave0 |= HAL_KEY_RIGHT;
        }
        else if ((adc >= 60) && (adc <= 73))
        {
          ksave0 |= HAL_KEY_LEFT;
        }
        else if ((adc >= 39) && (adc <= 59))
        {
          ksave0 |= HAL_KEY_DOWN;
        }
        else if ((adc >= 89) && (adc <= 100))
        {
          ksave0 |= HAL_KEY_CENTER;
        }
      } while (ksave0 != ksave1);
    
      return ksave0;
    }
    
    
    
    
    
    /**************************************************************************************************
     * @fn      halProcessKeyInterrupt
     *
     * @brief   Checks to see if it's a valid key interrupt, saves interrupt driven key states for
     *          processing by HalKeyRead(), and debounces keys by scheduling HalKeyRead() 25ms later.
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    void halProcessKeyInterrupt (void)
    {
      bool valid=FALSE;
    
      if (HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT)  /* Interrupt Flag has been set */
      {
        HAL_KEY_SW_6_PXIFG = ~(HAL_KEY_SW_6_BIT); /* Clear Interrupt Flag */
        valid = TRUE;
      }
    
      if (HAL_KEY_JOY_MOVE_PXIFG & HAL_KEY_JOY_MOVE_BIT)  /* Interrupt Flag has been set */
      {
        HAL_KEY_JOY_MOVE_PXIFG = ~(HAL_KEY_JOY_MOVE_BIT); /* Clear Interrupt Flag */
        valid = TRUE;
      }
    
      if (valid)
      {
        osal_start_timerEx (Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE);
      }
    }
    
    /**************************************************************************************************
     * @fn      HalKeyEnterSleep
     *
     * @brief  - Get called to enter sleep mode
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    void HalKeyEnterSleep ( void )
    {
    }
    
    /**************************************************************************************************
     * @fn      HalKeyExitSleep
     *
     * @brief   - Get called when sleep is over
     *
     * @param
     *
     * @return  - return saved keys
     **************************************************************************************************/
    uint8 HalKeyExitSleep ( void )
    {
      /* Wake up and read keys */
      return ( HalKeyRead () );
    }
    
    /***************************************************************************************************
     *                                    INTERRUPT SERVICE ROUTINE
     ***************************************************************************************************/
    
    /**************************************************************************************************
     * @fn      halKeyPort0Isr
     *
     * @brief   Port0 ISR
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    HAL_ISR_FUNCTION( halKeyPort0Isr, P0INT_VECTOR )
    {
      HAL_ENTER_ISR();
    
      if (HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT)
      {
        halProcessKeyInterrupt();
      }
    
      /*
        Clear the CPU interrupt flag for Port_0
        PxIFG has to be cleared before PxIF
      */
      HAL_KEY_SW_6_PXIFG = 0;
      HAL_KEY_CPU_PORT_0_IF = 0;
    
      CLEAR_SLEEP_MODE();
      HAL_EXIT_ISR();
    }
    
    
    /**************************************************************************************************
     * @fn      halKeyPort2Isr
     *
     * @brief   Port2 ISR
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    HAL_ISR_FUNCTION( halKeyPort2Isr, P2INT_VECTOR )
    {
      HAL_ENTER_ISR();
    
      if (HAL_KEY_JOY_MOVE_PXIFG & HAL_KEY_JOY_MOVE_BIT)
      {
        halProcessKeyInterrupt();
      }
    
      /*
        Clear the CPU interrupt flag for Port_2
        PxIFG has to be cleared before PxIF
        Notes: P2_1 and P2_2 are debug lines.
      */
      HAL_KEY_JOY_MOVE_PXIFG = 0;
      HAL_KEY_CPU_PORT_2_IF = 0;
    
      CLEAR_SLEEP_MODE();
      HAL_EXIT_ISR();
    }
    
    #else
    
    
    void HalKeyInit(void){}
    void HalKeyConfig(bool interruptEnable, halKeyCBack_t cback){}
    uint8 HalKeyRead(void){ return 0;}
    void HalKeyPoll(void){}
    
    #endif /* HAL_KEY */
    
    
    
    
    
    /**************************************************************************************************
    **************************************************************************************************/
    
    
    
    
    /**************************************************************************************************
      Filename:       zcl_genericapp.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 2006-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.
    **************************************************************************************************/
    
    /*********************************************************************
      This application is a template to get started writing an application
      from scratch.
    
      Look for the sections marked with "GENERICAPP_TODO" to add application
      specific code.
    
      Note: if you would like your application to support automatic attribute
      reporting, include the BDB_REPORTING compile flag.
    *********************************************************************/
    
    /*********************************************************************
     * INCLUDES
     */
    #include "ZComDef.h"
    #include "OSAL.h"
    #include "AF.h"
    #include "ZDApp.h"
    #include "ZDObject.h"
    #include "MT_SYS.h"
    
    #include "nwk_util.h"
    
    #include "zcl.h"
    #include "zcl_general.h"
    #include "zcl_ha.h"
    #include "zcl_diagnostic.h"
    #include "zcl_genericapp.h"
    
    #include "bdb.h"
    #include "bdb_interface.h"
    #include "gp_interface.h"
    
    #if defined ( INTER_PAN )
    #if defined ( BDB_TL_INITIATOR )
      #include "bdb_touchlink_initiator.h"
    #endif // BDB_TL_INITIATOR
    #if defined ( BDB_TL_TARGET )
      #include "bdb_touchlink_target.h"
    #endif // BDB_TL_TARGET
    #endif // INTER_PAN
    
    #if defined ( BDB_TL_INITIATOR ) || defined ( BDB_TL_TARGET )
      #include "bdb_touchlink.h"
    #endif
    
    #include "onboard.h"
    
    /* HAL */
    #include "hal_lcd.h"
    #include "hal_led.h"
    #include "hal_key.h"
    
    /*********************************************************************
     * MACROS
     */
    
    
    /*********************************************************************
     * CONSTANTS
     */
    
    
    /*********************************************************************
     * TYPEDEFS
     */
    
    /*********************************************************************
     * GLOBAL VARIABLES
     */
    byte zclGenericApp_TaskID;
    
    
    /*********************************************************************
     * GLOBAL FUNCTIONS
     */
    
    /*********************************************************************
     * LOCAL VARIABLES
     */
    
    uint8 giGenAppScreenMode = GENERIC_MAINMODE;   // display the main screen mode first
    
    uint8 gPermitDuration = 0;    // permit joining default to disabled
    
    devStates_t zclGenericApp_NwkState = DEV_INIT;
    
    
    /*********************************************************************
     * LOCAL FUNCTIONS
     */
    static void zclGenericApp_HandleKeys( byte shift, byte keys );
    static void zclGenericApp_BasicResetCB( void );
    static void zclGenericApp_ProcessIdentifyTimeChange( uint8 endpoint );
    static void zclGenericApp_BindNotification( bdbBindNotificationData_t *data );
    #if ( defined ( BDB_TL_TARGET ) && (BDB_TOUCHLINK_CAPABILITY_ENABLED == TRUE) )
    static void zclGenericApp_ProcessTouchlinkTargetEnable( uint8 enable );
    #endif
    
    static void zclGenericApp_ProcessCommissioningStatus(bdbCommissioningModeMsg_t *bdbCommissioningModeMsg);
    
    // app display functions
    static void zclGenericApp_LcdDisplayUpdate( void );
    #ifdef LCD_SUPPORTED
    static void zclGenericApp_LcdDisplayMainMode( void );
    static void zclGenericApp_LcdDisplayHelpMode( void );
    #endif
    
    // Functions to process ZCL Foundation incoming Command/Response messages
    static void zclGenericApp_ProcessIncomingMsg( zclIncomingMsg_t *msg );
    #ifdef ZCL_READ
    static uint8 zclGenericApp_ProcessInReadRspCmd( zclIncomingMsg_t *pInMsg );
    #endif
    #ifdef ZCL_WRITE
    static uint8 zclGenericApp_ProcessInWriteRspCmd( zclIncomingMsg_t *pInMsg );
    #endif
    static uint8 zclGenericApp_ProcessInDefaultRspCmd( zclIncomingMsg_t *pInMsg );
    #ifdef ZCL_DISCOVER
    static uint8 zclGenericApp_ProcessInDiscCmdsRspCmd( zclIncomingMsg_t *pInMsg );
    static uint8 zclGenericApp_ProcessInDiscAttrsRspCmd( zclIncomingMsg_t *pInMsg );
    static uint8 zclGenericApp_ProcessInDiscAttrsExtRspCmd( zclIncomingMsg_t *pInMsg );
    #endif
    
    /*********************************************************************
     * STATUS STRINGS
     */
    #ifdef LCD_SUPPORTED
    const char sDeviceName[]   = "  Generic App";
    const char sClearLine[]    = " ";
    const char sSwGenericApp[]      = "SW1:GENAPP_TODO";  // GENERICAPP_TODO
    const char sSwBDBMode[]     = "SW2: Start BDB";
    char sSwHelp[]             = "SW4: Help       ";  // last character is * if NWK open
    #endif
    
    /*********************************************************************
     * ZCL General Profile Callback table
     */
    static zclGeneral_AppCallbacks_t zclGenericApp_CmdCallbacks =
    {
      zclGenericApp_BasicResetCB,             // Basic Cluster Reset command
      NULL,                                   // Identify Trigger Effect command
      NULL,                                   // On/Off cluster commands
      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
    };
    
    /*********************************************************************
     * GENERICAPP_TODO: Add other callback structures for any additional application specific
     *       Clusters being used, see available callback structures below.
     *
     *       bdbTL_AppCallbacks_t
     *       zclApplianceControl_AppCallbacks_t
     *       zclApplianceEventsAlerts_AppCallbacks_t
     *       zclApplianceStatistics_AppCallbacks_t
     *       zclElectricalMeasurement_AppCallbacks_t
     *       zclGeneral_AppCallbacks_t
     *       zclGp_AppCallbacks_t
     *       zclHVAC_AppCallbacks_t
     *       zclLighting_AppCallbacks_t
     *       zclMS_AppCallbacks_t
     *       zclPollControl_AppCallbacks_t
     *       zclPowerProfile_AppCallbacks_t
     *       zclSS_AppCallbacks_t
     *
     */
    
    /*********************************************************************
     * @fn          zclGenericApp_Init
     *
     * @brief       Initialization function for the zclGeneral layer.
     *
     * @param       none
     *
     * @return      none
     */
    void zclGenericApp_Init( byte task_id )
    {
      zclGenericApp_TaskID = task_id;
    
      // This app is part of the Home Automation Profile
      bdb_RegisterSimpleDescriptor( &zclGenericApp_SimpleDesc );
    
      // Register the ZCL General Cluster Library callback functions
      zclGeneral_RegisterCmdCallbacks( GENERICAPP_ENDPOINT, &zclGenericApp_CmdCallbacks );
    
      // GENERICAPP_TODO: Register other cluster command callbacks here
    
      // Register the application's attribute list
      zcl_registerAttrList( GENERICAPP_ENDPOINT, zclGenericApp_NumAttributes, zclGenericApp_Attrs );
    
      // Register the Application to receive the unprocessed Foundation command/response messages
      zcl_registerForMsg( zclGenericApp_TaskID );
    
    #ifdef ZCL_DISCOVER
      // Register the application's command list
      zcl_registerCmdList( GENERICAPP_ENDPOINT, zclCmdsArraySize, zclGenericApp_Cmds );
    #endif
    
      // Register for all key events - This app will handle all key events
      RegisterForKeys( zclGenericApp_TaskID );
    
      bdb_RegisterCommissioningStatusCB( zclGenericApp_ProcessCommissioningStatus );
      bdb_RegisterIdentifyTimeChangeCB( zclGenericApp_ProcessIdentifyTimeChange );
      bdb_RegisterBindNotificationCB( zclGenericApp_BindNotification );
    
    #if ( defined ( BDB_TL_TARGET ) && (BDB_TOUCHLINK_CAPABILITY_ENABLED == TRUE) )
      bdb_RegisterTouchlinkTargetEnableCB( zclGenericApp_ProcessTouchlinkTargetEnable );
    #endif
    
    #ifdef ZCL_DIAGNOSTIC
      // Register the application's callback function to read/write attribute data.
      // This is only required when the attribute data format is unknown to ZCL.
      zcl_registerReadWriteCB( GENERICAPP_ENDPOINT, zclDiagnostic_ReadWriteAttrCB, NULL );
    
      if ( zclDiagnostic_InitStats() == ZSuccess )
      {
        // Here the user could start the timer to save Diagnostics to NV
      }
    #endif
    
    
    #ifdef LCD_SUPPORTED
      HalLcdWriteString ( (char *)sDeviceName, HAL_LCD_LINE_3 );
    #endif  // LCD_SUPPORTED
    
    
    }
    
    /*********************************************************************
     * @fn          zclSample_event_loop
     *
     * @brief       Event Loop Processor for zclGeneral.
     *
     * @param       none
     *
     * @return      none
     */
    uint16 zclGenericApp_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( zclGenericApp_TaskID )) )
        {
          switch ( MSGpkt->hdr.event )
          {
            case ZCL_INCOMING_MSG:
              // Incoming ZCL Foundation command/response messages
              zclGenericApp_ProcessIncomingMsg( (zclIncomingMsg_t *)MSGpkt );
              break;
    
            case KEY_CHANGE:
              zclGenericApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
              break;
    
            case ZDO_STATE_CHANGE:
              zclGenericApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
    
              // now on the network
              if ( (zclGenericApp_NwkState == DEV_ZB_COORD) ||
                   (zclGenericApp_NwkState == DEV_ROUTER)   ||
                   (zclGenericApp_NwkState == DEV_END_DEVICE) )
              {
                giGenAppScreenMode = GENERIC_MAINMODE;
                zclGenericApp_LcdDisplayUpdate();
              }
              break;
    
            default:
              break;
          }
    
          // Release the memory
          osal_msg_deallocate( (uint8 *)MSGpkt );
        }
    
        // return unprocessed events
        return (events ^ SYS_EVENT_MSG);
      }
    
      if ( events & GENERICAPP_MAIN_SCREEN_EVT )
      {
        giGenAppScreenMode = GENERIC_MAINMODE;
        zclGenericApp_LcdDisplayUpdate();
    
        return ( events ^ GENERICAPP_MAIN_SCREEN_EVT );
      }
    
    #if ZG_BUILD_ENDDEVICE_TYPE
      if ( events & GENERICAPP_END_DEVICE_REJOIN_EVT )
      {
        bdb_ZedAttemptRecoverNwk();
        return ( events ^ GENERICAPP_END_DEVICE_REJOIN_EVT );
      }
    #endif
    
      /* GENERICAPP_TODO: handle app events here */
    
    
      if ( events & GENERICAPP_EVT_1 )
      {
        // toggle LED 2 state, start another timer for 500ms
        HalLedSet ( HAL_LED_2, HAL_LED_MODE_TOGGLE );
        osal_start_timerEx( zclGenericApp_TaskID, GENERICAPP_EVT_1, 500 );
    
        return ( events ^ GENERICAPP_EVT_1 );
      }
    
      /*
      if ( events & GENERICAPP_EVT_2 )
      {
    
        return ( events ^ GENERICAPP_EVT_2 );
      }
    
      if ( events & GENERICAPP_EVT_3 )
      {
    
        return ( events ^ GENERICAPP_EVT_3 );
      }
      */
    
      // Discard unknown events
      return 0;
    }
    
    
    /*********************************************************************
     * @fn      zclGenericApp_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_2
     *                 HAL_KEY_SW_1
     *
     * @return  none
     */
    static void zclGenericApp_HandleKeys( byte shift, byte keys )
    {
      if ( keys & HAL_KEY_SW_6 )
      {
        static bool LED_OnOff = FALSE;
    
        giGenAppScreenMode = GENERIC_MAINMODE;
    
        /* GENERICAPP_TODO: add app functionality to hardware keys here */
    
        // for example, start/stop LED 2 toggling with 500ms period
        if (LED_OnOff)
        {
          // if the LED is blinking, stop the osal timer and turn the LED off
          osal_stop_timerEx(zclGenericApp_TaskID, GENERICAPP_EVT_1);
          HalLedSet ( HAL_LED_2, HAL_LED_MODE_OFF );
          LED_OnOff = FALSE;
        }
        else
        {
          // turn on LED 2 and start an osal timer to toggle it after 500ms, search
          // for GENERICAPP_EVT_1 to see event handling after expired timer
          osal_start_timerEx( zclGenericApp_TaskID, GENERICAPP_EVT_1, 500 );
          HalLedSet ( HAL_LED_2, HAL_LED_MODE_ON );
          LED_OnOff = TRUE;
        }
      }
      // Start the BDB commissioning method
      if ( keys & HAL_KEY_SW_6 )
      {
        giGenAppScreenMode = GENERIC_MAINMODE;
    
        bdb_StartCommissioning(BDB_COMMISSIONING_MODE_NWK_FORMATION | BDB_COMMISSIONING_MODE_NWK_STEERING | BDB_COMMISSIONING_MODE_FINDING_BINDING | BDB_COMMISSIONING_MODE_INITIATOR_TL);
      }
      if ( keys & HAL_KEY_SW_3 )
      {
        giGenAppScreenMode = GENERIC_MAINMODE;
    
        // touchlink target commissioning, if enabled
    #if ( defined ( BDB_TL_TARGET ) && (BDB_TOUCHLINK_CAPABILITY_ENABLED == TRUE) )
        bdb_StartCommissioning(BDB_COMMISSIONING_MODE_FINDING_BINDING);
        touchLinkTarget_EnableCommissioning( 30000 );
    #endif
    
      }
      if ( keys & HAL_KEY_SW_4 )
      {
    
       giGenAppScreenMode = giGenAppScreenMode ? GENERIC_MAINMODE : GENERIC_HELPMODE;
    #ifdef LCD_SUPPORTED
        HalLcdWriteString( (char *)sClearLine, HAL_LCD_LINE_2 );
    #endif
    
      }
      if ( keys & HAL_KEY_SW_5 )
      {
        bdb_resetLocalAction();
      }
    
      zclGenericApp_LcdDisplayUpdate();
    }
    
    /*********************************************************************
     * @fn      zclGenericApp_LcdDisplayUpdate
     *
     * @brief   Called to update the LCD display.
     *
     * @param   none
     *
     * @return  none
     */
    void zclGenericApp_LcdDisplayUpdate( void )
    {
    #ifdef LCD_SUPPORTED
      if ( giGenAppScreenMode == GENERIC_HELPMODE )
      {
        zclGenericApp_LcdDisplayHelpMode();
      }
      else
      {
        zclGenericApp_LcdDisplayMainMode();
      }
    #endif
    }
    
    #ifdef LCD_SUPPORTED
    /*********************************************************************
     * @fn      zclGenericApp_LcdDisplayMainMode
     *
     * @brief   Called to display the main screen on the LCD.
     *
     * @param   none
     *
     * @return  none
     */
    static void zclGenericApp_LcdDisplayMainMode( void )
    {
      // display line 1 to indicate NWK status
      if ( zclGenericApp_NwkState == DEV_ZB_COORD )
      {
        zclHA_LcdStatusLine1( ZCL_HA_STATUSLINE_ZC );
      }
      else if ( zclGenericApp_NwkState == DEV_ROUTER )
      {
        zclHA_LcdStatusLine1( ZCL_HA_STATUSLINE_ZR );
      }
      else if ( zclGenericApp_NwkState == DEV_END_DEVICE )
      {
        zclHA_LcdStatusLine1( ZCL_HA_STATUSLINE_ZED );
      }
    
      // end of line 3 displays permit join status (*)
      if ( gPermitDuration )
      {
        sSwHelp[15] = '*';
      }
      else
      {
        sSwHelp[15] = ' ';
      }
      HalLcdWriteString( (char *)sSwHelp, HAL_LCD_LINE_3 );
    }
    
    /*********************************************************************
     * @fn      zclGenericApp_LcdDisplayHelpMode
     *
     * @brief   Called to display the SW options on the LCD.
     *
     * @param   none
     *
     * @return  none
     */
    static void zclGenericApp_LcdDisplayHelpMode( void )
    {
      HalLcdWriteString( (char *)sSwGenericApp, HAL_LCD_LINE_1 );
      HalLcdWriteString( (char *)sSwBDBMode, HAL_LCD_LINE_2 );
      HalLcdWriteString( (char *)sSwHelp, HAL_LCD_LINE_3 );
    }
    #endif  // LCD_SUPPORTED
    
    /*********************************************************************
     * @fn      zclGenericApp_ProcessCommissioningStatus
     *
     * @brief   Callback in which the status of the commissioning process are reported
     *
     * @param   bdbCommissioningModeMsg - Context message of the status of a commissioning process
     *
     * @return  none
     */
    static void zclGenericApp_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(zclGenericApp_TaskID, GENERICAPP_END_DEVICE_REJOIN_EVT, GENERICAPP_END_DEVICE_REJOIN_DELAY);
          }
        break;
    #endif
      }
    }
    
    /*********************************************************************
     * @fn      zclGenericApp_ProcessIdentifyTimeChange
     *
     * @brief   Called to process any change to the IdentifyTime attribute.
     *
     * @param   endpoint - in which the identify has change
     *
     * @return  none
     */
    static void zclGenericApp_ProcessIdentifyTimeChange( uint8 endpoint )
    {
      (void) endpoint;
    
      if ( zclGenericApp_IdentifyTime > 0 )
      {
        HalLedBlink ( HAL_LED_2, 0xFF, HAL_LED_DEFAULT_DUTY_CYCLE, HAL_LED_DEFAULT_FLASH_TIME );
      }
      else
      {
        HalLedSet ( HAL_LED_2, HAL_LED_MODE_OFF );
      }
    }
    
    /*********************************************************************
     * @fn      zclGenericApp_BindNotification
     *
     * @brief   Called when a new bind is added.
     *
     * @param   data - pointer to new bind data
     *
     * @return  none
     */
    static void zclGenericApp_BindNotification( bdbBindNotificationData_t *data )
    {
      // GENERICAPP_TODO: process the new bind information
    }
    
    
    /*********************************************************************
     * @fn      zclGenericApp_ProcessTouchlinkTargetEnable
     *
     * @brief   Called to process when the touchlink target functionality
     *          is enabled or disabled
     *
     * @param   none
     *
     * @return  none
     */
    #if ( defined ( BDB_TL_TARGET ) && (BDB_TOUCHLINK_CAPABILITY_ENABLED == TRUE) )
    static void zclGenericApp_ProcessTouchlinkTargetEnable( uint8 enable )
    {
      if ( enable )
      {
        HalLedSet ( HAL_LED_1, HAL_LED_MODE_ON );
      }
      else
      {
        HalLedSet ( HAL_LED_1, HAL_LED_MODE_OFF );
      }
    }
    #endif
    
    /*********************************************************************
     * @fn      zclGenericApp_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 zclGenericApp_BasicResetCB( void )
    {
    
      /* GENERICAPP_TODO: remember to update this function with any
         application-specific cluster attribute variables */
    
      zclGenericApp_ResetAttributesToDefaultValues();
    
    }
    /******************************************************************************
     *
     *  Functions for processing ZCL Foundation incoming Command/Response messages
     *
     *****************************************************************************/
    
    /*********************************************************************
     * @fn      zclGenericApp_ProcessIncomingMsg
     *
     * @brief   Process ZCL Foundation incoming message
     *
     * @param   pInMsg - pointer to the received message
     *
     * @return  none
     */
    static void zclGenericApp_ProcessIncomingMsg( zclIncomingMsg_t *pInMsg )
    {
      switch ( pInMsg->zclHdr.commandID )
      {
    #ifdef ZCL_READ
        case ZCL_CMD_READ_RSP:
          zclGenericApp_ProcessInReadRspCmd( pInMsg );
          break;
    #endif
    #ifdef ZCL_WRITE
        case ZCL_CMD_WRITE_RSP:
          zclGenericApp_ProcessInWriteRspCmd( pInMsg );
          break;
    #endif
        case ZCL_CMD_CONFIG_REPORT:
        case ZCL_CMD_CONFIG_REPORT_RSP:
        case ZCL_CMD_READ_REPORT_CFG:
        case ZCL_CMD_READ_REPORT_CFG_RSP:
        case ZCL_CMD_REPORT:
          //bdb_ProcessIncomingReportingMsg( pInMsg );
          break;
    
        case ZCL_CMD_DEFAULT_RSP:
          zclGenericApp_ProcessInDefaultRspCmd( pInMsg );
          break;
    #ifdef ZCL_DISCOVER
        case ZCL_CMD_DISCOVER_CMDS_RECEIVED_RSP:
          zclGenericApp_ProcessInDiscCmdsRspCmd( pInMsg );
          break;
    
        case ZCL_CMD_DISCOVER_CMDS_GEN_RSP:
          zclGenericApp_ProcessInDiscCmdsRspCmd( pInMsg );
          break;
    
        case ZCL_CMD_DISCOVER_ATTRS_RSP:
          zclGenericApp_ProcessInDiscAttrsRspCmd( pInMsg );
          break;
    
        case ZCL_CMD_DISCOVER_ATTRS_EXT_RSP:
          zclGenericApp_ProcessInDiscAttrsExtRspCmd( pInMsg );
          break;
    #endif
        default:
          break;
      }
    
      if ( pInMsg->attrCmd )
        osal_mem_free( pInMsg->attrCmd );
    }
    
    #ifdef ZCL_READ
    /*********************************************************************
     * @fn      zclGenericApp_ProcessInReadRspCmd
     *
     * @brief   Process the "Profile" Read Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclGenericApp_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      zclGenericApp_ProcessInWriteRspCmd
     *
     * @brief   Process the "Profile" Write Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclGenericApp_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      zclGenericApp_ProcessInDefaultRspCmd
     *
     * @brief   Process the "Profile" Default Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclGenericApp_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      zclGenericApp_ProcessInDiscCmdsRspCmd
     *
     * @brief   Process the Discover Commands Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclGenericApp_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      zclGenericApp_ProcessInDiscAttrsRspCmd
     *
     * @brief   Process the "Profile" Discover Attributes Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclGenericApp_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      zclGenericApp_ProcessInDiscAttrsExtRspCmd
     *
     * @brief   Process the "Profile" Discover Attributes Extended Response Command
     *
     * @param   pInMsg - incoming message to process
     *
     * @return  none
     */
    static uint8 zclGenericApp_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
    
    /****************************************************************************
    ****************************************************************************/
    
    
    

  • As I replied, you can refer to SampleTemperatureSensor example to see how to report temperature with ZCL reporting command.
  • Thank you YK Chen. Let me try it. If i use the SampleTemperatureSensor for EndDevice i assume i must use the SampleThermostat as my Coordinator. Is my assumption correct?
  • No, it’s not necessary to use SampleThermostat. Any coordinator supports ZCL temperature cluster can receive temperature data in ZCL format.
  • Thank you again YK Chen for your quick response. Let me try it and post my observation.
  • As you mentioned i ran the SampleTemperatureSensor example on my Coordinator and EndDevice. Please find the attached cubx file for the same.

    Steps followed:-

    1. Started Coordinator and ran device commissioning
    2. Started EndDevice and ran device commissioning
    3. Using Key input on EndDevice and invoked zclSampleTemperatureSensor_UiActionChangeTemp() to report change in temperature.

    SampleTemperatureSesnor_log.zip

  • I think you don’t put ZCL temperature cluster in your coordinator and device so it doesn’t bind successfully.
  • I'm sorry could you please guide me which file and function to look at?
  • You can try to search ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT in zcl_sampletemperaturesensor_data.c to see how to add ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT and its attributes to zclSampleTemperatureSensor_InClusterList and attach it to zclSampleTemperatureSensor_SimpleDesc for application usage.
  • Thank you very much YK Chen for your reply. Should i register a new endpoint using afRegister()?
  • You can use the same endpoint of GenericApp.
  • Hello YiKai Chen i could not able to get the sample temperature sensor running. Instead, i tried running the sample light (as coordinator) and sample switch (as end device) to get my network up and running. I found that with these two software i can able to get the coordinator and end device exchange the key and hence i can read the decrypted payload on packet sniffer (please refer the attached log). However, i still cannot get the end device to send a ZCL_CLUSTER_ID_GEN_ON_OFF to coordinator. From the log i see only the Identify Query sent by client and the server acks the request with a response.

    Could you help me isolating the problem in my side?

    SampleLight-SampleSwitch_log.zip

  • There must be something wrong in your finding and binding. Do you start finding and binding about the same time from both coordinator and device to make them binding.
  • I would say yes. I start both coordinator and and end device at the same time but i start the commissioning process on coordinator first and then the end device. Is there a way to get finding and binding status at coordinator end? if so i can wait until it completes and then start the end device commissioning process.

    Also from my previous log posted i see multiple Simple Descriptor Request from End Device to Coordinator where there is a acknowledgement (img1) after which there are multiple Simple Descriptor Request for which there are no acknowledgment. After this the end device rejoin the coordinator. Is this a normal behavior? What is the significance of Simple Descriptor Request?

    img1 --

    img2 --

  • Don’t know how to help on your specific HW.
  • I was able to get the simple light and simple switch working in my network. Please refer the attached log file.SimpleLight-SimpleSwitch.cubx.zip

  • It's good to know it works now.
  • Can i have measurement cluster and On/Off cluster in the same endpoint? or i must create two end points?
  • Yes, you can have them in the same endpoint.