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.

Multiple End point creation on end device in Zigbee

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

Hi,

      I am trying to add multiple end points to the end point using CC2652 TI EVK boards.

      I am using two EVK boards. One act as switch which has the co-ordinator role and the other act as light which has the end device role. 

     The end device EVK has two leds green and red. I wanted to control these two leds individually. So I created two end points at the end device side .

     And at the co-ordinator [switch] side , the found the following code

 

void zclSampleSw_UiActionToggleLight(uint16 keys) //Anjali
{
        if (zclSampleSw_OnOffSwitchActions == ON_OFF_SWITCH_ACTIONS_TOGGLE)
         {
            if (keys & UI_KEY_SW_5_PRESSED)
                  {
                            zstack_bdbGetZCLFrameCounterRsp_t Rsp;

                            Zstackapi_bdbGetZCLFrameCounterReq(zclSampleSw_Entity, &Rsp);

                            zclGeneral_SendOnOff_CmdToggle( SAMPLESW_ENDPOINT, &zclSampleSw_DstAddr, FALSE, Rsp.zclFrameCounter );

             }

else
        {
              // Other zclSampleSw_OnOffSwitchActions are not supported by this UI
        }
  }
}

Here the code line    zclGeneral_SendOnOff_CmdToggle( SAMPLESW_ENDPOINT, &zclSampleSw_DstAddr, FALSE, Rsp.zclFrameCounter ); send the command to SAMPLESW_ENDPOINT which is defined for the red led control , but here green led also getting controlled. 

Could anyone please help with this issue?

  • I suggest you to use sniffer to check what happens over the air.

  • Hi Anjali,

    If you're modifying from the example projects, I believe finding & binding is automatically creating binds from the switch to both lights, which allows the switch to control both lights.
    Also, by default, the examples use indirect addressing (see zclSampleSw_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent; in zcl_samplesw.c). That's why the binding table is used to find the correct device(s) to send the toggle command. If you know the address and endpoint of the device you want to send the toggle command, you can specify those in zclSampleSw_DstAddr.
    You can read more about addressing and binding in sections 3 and 4 of Z-Stack Overview: http://dev.ti.com/tirex/content/simplelink_zigbee_sdk_plugin_1_60_00_14/docs/zigbee_user_guide/html/zigbee/developing_zigbee_applications/z_stack_developers_guide/z-stack-overview.html

    In addition to sending some sniffer logs, please also share the relevant code that you use to set up the two light endpoints on one device, so we can reproduce the issue for further analysis.


    Regards,
    Toby

  • Hi Toby,

     Thank You for the reply. As per your reply , I changed the code in co-ordinator [switch ] side as below.

    zclSampleSw_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;  //For unicast addressing
    zclSampleSw_DstAddr.endPoint = 9;
    zclSampleSw_DstAddr.addr.shortAddr = 0;

    //Register Endpoint
    zclSampleSwEpDesc.endPoint = SAMPLESW_ENDPOINT;
    zclSampleSwEpDesc.simpleDesc = &zclSampleSw_SimpleDesc;
    zclport_registerEndpoint(zclSampleSw_Entity, &zclSampleSwEpDesc);

    // Register the ZCL General Cluster Library callback functions
    zclGeneral_RegisterCmdCallbacks( SAMPLESW_ENDPOINT, &zclSampleSw_CmdCallbacks );

    // Register the application's attribute list and reset to default values
    zclSampleSw_ResetAttributesToDefaultValues();
    zcl_registerAttrList( SAMPLESW_ENDPOINT, zclSampleSw_NumAttributes, zclSampleSw_Attrs );

            

    And light side registered two end points

    static void zclSampleLight_Init( void )
    {

    // Set destination address to indirect
    zclSampleLight_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent;
    zclSampleLight_DstAddr.endPoint = 0;
    zclSampleLight_DstAddr.addr.shortAddr = 0;

    //Register Endpoint
    zclSampleLightEpDesc.endPoint = SAMPLELIGHT_ENDPOINT;
    zclSampleLightEpDesc.simpleDesc = &zclSampleLight_SimpleDesc;
    zclport_registerEndpoint(zclSampleLight_Entity, &zclSampleLightEpDesc);


    // Register the ZCL General Cluster Library callback functions
    zclGeneral_RegisterCmdCallbacks( SAMPLELIGHT_ENDPOINT, &zclSampleLight_CmdCallbacks );

    // Register the application's attribute list and reset to default values
    zclSampleLight_ResetAttributesToDefaultValues();
    zcl_registerAttrList( SAMPLELIGHT_ENDPOINT, zclSampleLight_NumAttributes, zclSampleLight_Attrs );

    /* For the second endpoint */

    #if 1
    // Set destination address to indirect
    zclSampleLight_DstAddr_1.addrMode = (afAddrMode_t)AddrNotPresent;
    zclSampleLight_DstAddr_1.endPoint = 0;
    zclSampleLight_DstAddr_1.addr.shortAddr = 0;

    //Register Endpoint
    zclSampleLightEpDesc_1.endPoint = SAMPLELIGHT_ENDPOINT_1;
    zclSampleLightEpDesc_1.simpleDesc = &zclSampleLight_SimpleDesc_1;
    zclport_registerEndpoint(zclSampleLight_Entity, &zclSampleLightEpDesc_1);


    // Register the ZCL General Cluster Library callback functions
    zclGeneral_RegisterCmdCallbacks( SAMPLELIGHT_ENDPOINT_1, &zclSampleLight_CmdCallbacks_1 );

    // Register the application's attribute list and reset to default values
    zclSampleLight_ResetAttributesToDefaultValues();
    zcl_registerAttrList( SAMPLELIGHT_ENDPOINT_1, zclSampleLight_NumAttributes, zclSampleLight_Attrs );

    #endif

    // Register the Application to receive the unprocessed Foundation command/response messages
    zclport_registerZclHandleExternal(zclSampleLight_ProcessIncomingMsg);


    //Write the bdb initialization parameters
    zclSampleLight_initParameters();

    //Setup ZDO callbacks
    SetupZStackCallbacks();

    #ifdef ZCL_LEVEL_CTRL
    zclSampleLight_LevelLastLevel = zclSampleLight_LevelCurrentLevel;
    #endif


    #ifdef ZCL_DISCOVER
    // Register the application's command list
    zcl_registerCmdList( SAMPLELIGHT_ENDPOINT, zclCmdsArraySize, zclSampleLight_Cmds );
    zcl_registerCmdList( SAMPLELIGHT_ENDPOINT_1, zclCmdsArraySize, zclSampleLight_Cmds );

    #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( SAMPLELIGHT_ENDPOINT, zclDiagnostic_ReadWriteAttrCB, NULL );

    if ( zclDiagnostic_InitStats() == ZSuccess )
    {
    // Here the user could start the timer to save Diagnostics to NV
    }
    #endif

    UI_Init(zclSampleLight_Entity, &events, sem, SAMPLEAPP_LCD_AUTO_UPDATE_EVT, SAMPLEAPP_PROCESS_UI_UART_EVT, &zclSampleLight_IdentifyTime, APP_TITLE, &zclSampleLight_UiUpdateLcd, zclSampleLight_UiStatesMain);


    #if defined ( BDB_TL_INITIATOR )
    touchLinkInitiatorApp_Init(zclSampleLight_Entity);
    #elif defined ( BDB_TL_TARGET )
    touchLinkTargetApp_Init(zclSampleLight_Entity);
    #endif

    UI_UpdateLcd();
    }

    I have duplicated the code in light side for two end points [8 and 9]. And from switch side I issued the below command for the endpoint 9

     zclGeneral_SendOnOff_CmdToggle( 9, &zclSampleSw_DstAddr, FALSE, Rsp.zclFrameCounter ); //zclSampleSw_DstAddr is set as Addr16Bit mode

    But now I am not able to control any LEDS. When I checked the sniffer log, no ON/OFF Toggle command is found . What am I missing?

  • Please send sniffer logs for both before and after the change.

    As for the code on the coordinator side, you also need to set zclSampleSw_DstAddr.addr.shortAddr and zclSampleSw_DstAddr.endPoint to the short address (ie network address) and end point of the specific light you want to control.
  • Thank you for the reply. 

    I ll share the sniffer capture logs soon. Before that  a quick question on the short address. I had once set it to the address of the light which I got to know through the sniffer capture logs.

    After setting that address also things didn't work and I noticed that the short address keeps on changing or dynamic in nature.

    Is there any other procedure  to set the short address as static?

  • Short address shouldn’t change after device joins a Zigbee network if your device enable NV_RESTORE.
  • That's expected, since Zigbee PRO uses a stochastic (random) addressing scheme.

    With that said, you can still find the short address of the joining device from the coordinator side:
    When the end device joins, it will broadcast a Device Announce command. This command contains the short address (also called network address) of the end device.
    When the switch coordinator receives this command, it will process it in zclSampleSw_processZStackMsgs. In this situation, the zstackmsg_CmdIDs_ZDO_DEVICE_ANNOUNCE case will handle the message.
    Then you can use ((zstackmsg_zdoDeviceAnnounceInd_t*)pMsg)->req.srcAddr for the short address of the end device.
  • Hi Toby,

    ((zstackmsg_zdoDeviceAnnounceInd_t*)pMsg)->req.srcAddr is not matching with the short address we obtained through Ubiqua Sniffer. But from the Ubiqua Sniffer MAC Dest Addr and address printed on the serial terminal after commissioned are matching.

    So, in zstack.h can we use the dstAddr member in zstack_zdoActiveEndpointReq_t structure and assign it to the shortAddr of the endpoint in the coordinator toggle command?

    Thanks & Regards,
    Yasar Arafath
  • Are you are reading the ((zstackmsg_zdoDeviceAnnounceInd_t*)pMsg)->req.srcAddr in

    case zstackmsg_CmdIDs_BDB_TC_LINK_KEY_EXCHANGE_NOTIFICATION_IND:
    case zstackmsg_CmdIDs_AF_DATA_CONFIRM_IND:
    break;
    case zstackmsg_CmdIDs_ZDO_DEVICE_ANNOUNCE:
       // reading short address here?
    break;
    case zstackmsg_CmdIDs_ZDO_NWK_ADDR_RSP:

    There are multiple ways you can get the address of the end device. If you have verified that the destination address you're using is the correct one, then please proceed.

    Regards,

    Toby

  • Hi Toby,

    Yes, we read ((zstackmsg_zdoDeviceAnnounceInd_t*)pMsg)->req.srcAddr from here only.
    case zstackmsg_CmdIDs_ZDO_DEVICE_ANNOUNCE:
    zclSampleSw_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
    zclSampleSw_DstAddr.endPoint = 8;
    zclSampleSw_DstAddr.addr.shortAddr = ((zstackmsg_zdoDeviceAnnounceInd_t*)pMsg)->req.srcAddr ;

    Also we are telling the 16 bit addressing and the ENDPOINT number also. Is the above method is correct or no need to change the addressing mode?

    But when reading dstAddr member in zstack_zdoActiveEndpointReq_t structure also doesnt helps.

    Thanks & Regards,
    Yasar Arafath
  • Yes, that looks correct.

    Note the additional "break;" statements I added in the previous post (they're added so that, for example, zstackmsg_CmdIDs_BDB_TC_LINK_KEY_EXCHANGE_NOTIFICATION_IND case and zstackmsg_CmdIDs_AF_DATA_CONFIRM_IND case are not combined with the zstackmsg_CmdIDs_ZDO_DEVICE_ANNOUNCE case).

    The short address is the same for both light endpoints on the end device. Only the endpoints will differ. Fill in the appropriate endpoint for the light you wish to control.
    If the endpoint numbers are not known ahead of time, you can use Zstackapi_ZdoActiveEndpointReq to request a list of endpoints for a particular end device. When the end device receives that message, it will send a list of all active endpoints it supports. The coordinator can process this message in the zstackmsg_CmdIDs_ZDO_ACTIVE_EP_RSP case of zclSampleSw_processZStackMsgs.