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.

ZCL Write string to attribute

Other Parts Discussed in Thread: Z-STACK, CC2650, CC2530

Hi all. 

I have a problem writing a string to attribute. I've managed to read and write uint8 type attribute, but when I try to write string to ATTRID_BASIC_LOCATION_DESC, attribute is empty when read.

Can anyone post an example for writing string to ATTRID_BASIC_LOCATION_DESC attribute (ZCL_CLUSTER_ID_GEN_BASIC). I'm using sampleswitch app to learn zstack.

And If I want to write local attribute, should I still use zcl_SendWrite()? Thanks.

  • Do you add ATTRID_BASIC_LOCATION_DESC support in your device simple descriptor? If possible, please provide packer sniffer log to better understanding your problem.
  • Hi YiKai

    In my case, I want to use  "zcl_SendWrite" to write attribute of Server side, which is only ATTRID_BASIC_LOCATION_DESC attribute.

    The code is based on DoorlockController & Doorlock sample proj.

    Once I call change location function, Server side cannot catch any RF packet data.

    below is my code :

    static void DLCSApp_changeLocation(void)
    {
    	zclWriteCmd_t *writeCmd;
    	afAddrType_t dstAddr;
    
      	writeCmd = (zclWriteCmd_t *)zcl_mem_alloc( sizeof( zclWriteCmd_t ) + ( 1 * sizeof( zclWriteRec_t ) ) );
    	writeCmd->numAttr = 1;
    	writeCmd->attrList[0].attrID = ATTRID_BASIC_LOCATION_DESC; // attr id
    	writeCmd->attrList[0].dataType = ZCL_DATATYPE_CHAR_STR;	   // data type
    	writeCmd->attrList[0].attrData = "Location"; //buffer
    
    	dstAddr.addrMode = (afAddrMode_t)zdlcDstAddr.addrMode;
            dstAddr.addr.shortAddr = zdlcDstAddr.addr.shortAddr;
            dstAddr.endPoint = zdlcDstAddr.endpoint;
            dstAddr.panId = zdlcDstAddr.panID;
    	
    	zcl_SendWrite(DLCSAPP_EP, &dstAddr, ZCL_CLUSTER_ID_GEN_BASIC, writeCmd, ZCL_FRAME_CLIENT_SERVER_DIR, 0, 0);
    }

    Please suggest me what is the problem

  • Can you show me how you declare ATTRID_BASIC_LOCATION_DESC attribute on server side?
  • Hi YiKai,

    Thanks for your quick reply.

    Below code is for ATTRID_BASIC_LOCATION_DESC attribute .

    /*********************************************************************
     * ATTRIBUTE DEFINITIONS - Uses REAL cluster IDs
     */
    CONST zclAttrRec_t zclSampleDoorLock_Attrs[SAMPLEDOORLOCK_MAX_ATTRIBUTES] =
    {
                 // ...........
      // *** General Basic Cluster Attributes ***
    {
        ZCL_CLUSTER_ID_GEN_BASIC,
        { // Attribute record
          ATTRID_BASIC_LOCATION_DESC,
          ZCL_DATATYPE_CHAR_STR,
          (ACCESS_CONTROL_READ | ACCESS_CONTROL_WRITE),
          (void *)zclSampleDoorLock_LocationDescription
        }
      },
                 // ..........
    }

    Thanks

  • Try to set a breakpoint in "case ZCL_CMD_WRITE:" of zclSampleDoorLock_ProcessFoundationMsg and trace what's wrong with it.
  • Hi YiKai

    I set breakpoint at server side which located at zclSampleDoorLock_ProcessFoundationMsg  as you told me.

    But when I send write command from client side, server side cannot receive anything, exactly. Breakpoint also cannot be hit.

    Please see attached picture which is captured at client side. when I click some button to trigger send write command writeCmd variable value show nothing.

    what is the problem?

  • I would suggest you to use Ubiqua Packet Analyzer to check over the air message first.
  • Actually, I don't have ubiqua tool.

    can I use z-tool to capture sniffer packet?

    If yes, I already use z-tool to check packet.

    z-tool can show me the packet log during send door lock/unlock command from client.

    but write attribute command cannot show anything with z-tool.

  • No, Ztool is not for this purpose. If you don't have Ubiqua Packet Analyzer, you can use TI packet sniffer.
  • Hi YiKai,

    I use TI Packet sniffer tool to capture OTA packet, when I trigger write attribute command from client, I cannot see such of packet.

    I think the problem caused by write command, 

    static void DLCSApp_changeLocation(void)
    {
    	zclWriteCmd_t *writeCmd;
    	afAddrType_t dstAddr;
    
      	writeCmd = (zclWriteCmd_t *)zcl_mem_alloc( sizeof( zclWriteCmd_t ) + ( 1 * sizeof( zclWriteRec_t ) ) );
    	writeCmd->numAttr = 1;
    	writeCmd->attrList[0].attrID = ATTRID_BASIC_LOCATION_DESC; // attr id
    	writeCmd->attrList[0].dataType = ZCL_DATATYPE_CHAR_STR;	   // data type
    	writeCmd->attrList[0].attrData = "songrym"; //buffer
    
    	writeRec111.attrID = ATTRID_BASIC_LOCATION_DESC;
    	
    	dstAddr.addrMode = (afAddrMode_t)zdlcDstAddr.addrMode;
        dstAddr.addr.shortAddr = zdlcDstAddr.addr.shortAddr;
        dstAddr.endPoint = zdlcDstAddr.endpoint;
        dstAddr.panId = zdlcDstAddr.panID;
    	
    	zcl_SendWrite(DLCSAPP_EP, &dstAddr, ZCL_CLUSTER_ID_GEN_BASIC, writeCmd, ZCL_FRAME_CLIENT_SERVER_DIR, 0, 0);
    }

    As I post debug image yesterday, before call zcl_SendWrite function, writeCmd variable value is abnormal. 

    what is yr opinion?

  • What do you mean "writeCmd variable value is abnormal?"
  • Hi YiKai

    In DLCSApp_changeLocation function call, I used zclWriteCmd_t *writeCmd to assign command data. (refer above src code)

    finally assign the write command I call zcl_SendWrite function to write command over the air to server side.

    With debugging mode, I checked writeCmd variable in Local tab, find that there is no value assign in it.

  • That is because IAR cannot watch local variable. You can declare it as static like "static zclWriteCmd_t *writeCmd;" and you can watch it.
  • Hi YiKai

    Please see below picture, what is captured by packet sniffer.

    when I trigger send write attribute command, there is nothing special packet over the air.

    ==================================== send write attribute command =============================================

    ===================================== send change light level control command ======================================

    If I send change light level command, sniffer packet shown as below picture.

  • Try to check return status of zcl_SendWrite first.
  • Hi YiKai

    Thanks for your suggest.

    I checked zcl_SendWrite return value, it cannot return ZSuccess.

    Means that write attribute fail at client side.

    Please help me, what is problem

  • writeCmd->attrList[0].attrData is an uint8 pointer so you can't assign it like "writeCmd->attrList[0].attrData = "Location";". By the way, you should check what is set to dstAddr structure.
  • Hi YiKai.
    dstAddr structure is set same with zswDstAddr of sample switch.

    zswDstAddr.addrMode = zstack_AFAddrMode_NONE;
    zswDstAddr.addr.shortAddr = 0;
    zswDstAddr.endpoint = 0;
    zswDstAddr.panID = 0;

    with this setting, can send light on/off command without any problem.
  • Endpoint cannot be 0.
  • I set breakpoint at zcl_SendCommand function, which is located at zcl.c file.
    and when I send write attribute command, the breakpoint will be hit at zcl_SendCommand.
    I checked srcEP value, the value is set as 0x00. as you know switchEP is 0x06.
    Before send write attribute command, I was setting srcEP as 0x06, after run to zcl_SendCommand function, it was changed as 0x00..
  • What is zstack_AFAddrMode_NONE?
  • Hi YiKai.
    Every sample project of simpleLink(cc26xx), at SampleApp_initialization set as below.

    /* Initialize variables */
    ztsDstAddr.addrMode = zstack_AFAddrMode_NONE;
    ztsDstAddr.addr.shortAddr = 0;
    ztsDstAddr.endpoint = 0;
    ztsDstAddr.panID = 0;

    Actually, zstack_AFAddrMode_NONE define as 0, means that Address not present.
  • OK, you use Z-Stack for CC26xx. If you use Address not present mode, do you do binding before you use it?
  • Sample Switch project use default as EZ-Mode, is it need to binding process?
    I just use Sample switch as base, just add simple function which is change location attribute of server side.
    Except change location function, I didn't modify anymore.
  • Can you specify what is your coordinator and what role your switch project is?
  • Sorry for that I didn't give you much more information,

    Now I am using CC2538EM as SampleLight (ZC - server), CC2650EM as SampleSwitch (ZED - client)
    Z-Stack: zstack Home 1.2.2

    Refer that I didn't change any source code except adding change location function in switch.c of CC2650 side .
    Using change location function I want to change Server side ATTRID_BASIC_LOCATION_DESC.

    Can you help me to solve this issue?
  • EZ mode only does binding from SampleSwitch to SampleLight in this case. Now, you won't to send write attribute from SampleLight to SampleSwitch and there is no binding. I would suggest you to use short address and active endpoint of SampleSwitch to send write attribute from SampleLight.
  • Hi YiKai

    I didn't write code for sending write attribute command at SampleLight project.

    Now my case is that write attribute command is send from SampleSwitch to SampleLight.

    In Switch application when I send toggle command to Light, the short address and end point are set as 0x00.

    If you want, I can attach whole switch project file to let you review my code.

  • I would suggest you set a breakpoint at zcl_SendWrite and trace into it to see why it doesn't return success.
  • Hi  Songrym Nam

           do  you have find out what is  the problem  of your code?

           if  not, maybe  you  could  have a  try of  below code :

          

    static void DLCSApp_changeLocation(void)
    {
    	zclWriteCmd_t *writeCmd;
    	afAddrType_t dstAddr;
            uint8 Location_buf[] = { 8, 'L','o','c','a','t','i','o','n' };
    
      	writeCmd = (zclWriteCmd_t *)zcl_mem_alloc( sizeof( zclWriteCmd_t ) + ( 1 * sizeof( zclWriteRec_t ) ) );
    	writeCmd->numAttr = 1;
    	writeCmd->attrList[0].attrID = ATTRID_BASIC_LOCATION_DESC; // attr id
    	writeCmd->attrList[0].dataType = ZCL_DATATYPE_CHAR_STR;	   // data type
    	writeCmd->attrList[0].attrData = Location_buf; //buffer
    
    	dstAddr.addrMode = (afAddrMode_t)zdlcDstAddr.addrMode;
            dstAddr.addr.shortAddr = zdlcDstAddr.addr.shortAddr;
            dstAddr.endPoint = zdlcDstAddr.endpoint;
            dstAddr.panId = zdlcDstAddr.panID;
    	
    	zcl_SendWrite(DLCSAPP_EP, &dstAddr, ZCL_CLUSTER_ID_GEN_BASIC, writeCmd, ZCL_FRAME_CLIENT_SERVER_DIR, 0, 0);
    }

    as  i  think it maybe the size of attrData is different with the one which get by zclGetAttrDataLength() function;

      eg:

           1.  zcl_SendWirte()  function will call  zcl_SendWriteRequest(),  

           2.  then zcl_SendWriteRequest()  will call zclGetAttrDataLength()  to get the dataLen 

          

    uint16 zclGetAttrDataLength( uint8 dataType, uint8 *pData )
    {
      uint16 dataLen = 0;
    
      if ( dataType == ZCL_DATATYPE_LONG_CHAR_STR || dataType == ZCL_DATATYPE_LONG_OCTET_STR )
      {
        dataLen = BUILD_UINT16( pData[0], pData[1] ) + 2; // long string length + 2 for length field
      }
      else if ( dataType == ZCL_DATATYPE_CHAR_STR || dataType == ZCL_DATATYPE_OCTET_STR )
      {
        dataLen = *pData + 1; // string length + 1 for length field
      }
      else
      {
        dataLen = zclGetDataTypeLength( dataType );
      }
    
      return ( dataLen );
    }
    

               3.   writeCmd->attrList[0].attrData = "Location"; //buffer

            *pData  is 'L' 

    BR!

          

  • Thanks for you reply.
    I change location buf as you told me above, zcl_SendWrite return ZSuccess. GOOD!!
    If write attribute command send correctly, which kind of packet should I need to watch in sniffer packet tool?
    I can see many fields in whole packet (ex, MAC HDR, BCON, DATA, NWK LAYER... ),
    I need to verify whether packet send or not.

    So sorry that I am a newbie in Zigbee technology that may ask you guys a foolish question..
  • You can attach your sniffer log so I can have a look on it.
  • Hi Yikai,

    See below picture what is captured at time of send attribute cmd.

    Seems that no relative packet send out by Switch side.

  • Can you attach sniffer log file not a screen shot only?
  • Hi, YiKai

    Please refer attached psd file

    Thankspacket.psd

  • Yes, there is nothing sent in your sniffer log. Since your destination is coordinator, I would suggest you to use short address to send and see if it works.
  • Hi YiKai,

    I am not so clear about your suggestion,

    Is it means that set dstAddr.addr.shortAddr as coordinator short address?

    If so, coordinator short address is default 0x00, how should I set ?

    dstAddr.addrMode = (afAddrMode_t)zdlcDstAddr.addrMode;
    dstAddr.addr.shortAddr = 0x00;   // it is already set as 0x00
    dstAddr.endPoint = zdlcDstAddr.endpoint;
    dstAddr.panId = zdlcDstAddr.panID;
  • You should use afAddr16Bit as address mode and endpoint should be active endpoint of coordinator.
  • Hi YiKai.

    I change my code as shown below:

    dstAddr1.addrMode = afAddr16Bit;
    dstAddr1.addr.shortAddr = zswDstAddr.addr.shortAddr;
    dstAddr1.endPoint = 0x08;
    dstAddr1.panId = zswDstAddr.panID;

    When I send command, I can captured some packet as attached. seems that something send out from switch side.

    If it is relative command to light, at light side where should I set break point to check receiving message ?

    location_cap.psd

  • I see the write attribute command is sent in the attached sniffer log. You can try to set a breakpoint in zclProcessInWriteCmd to check receiving it.
  • Hi  Yikai

           does   below  code  not work?

    static void DLCSApp_changeLocation(void)
    {
    	zclWriteCmd_t *writeCmd;
    	afAddrType_t dstAddr;
            uint8 Location_buf[] = { 8, 'L','o','c','a','t','i','o','n' };
    
      	writeCmd = (zclWriteCmd_t *)zcl_mem_alloc( sizeof( zclWriteCmd_t ) + ( 1 * sizeof( zclWriteRec_t ) ) );
    	writeCmd->numAttr = 1;
    	writeCmd->attrList[0].attrID = ATTRID_BASIC_LOCATION_DESC; // attr id
    	writeCmd->attrList[0].dataType = ZCL_DATATYPE_CHAR_STR;	   // data type
    	writeCmd->attrList[0].attrData = Location_buf; //buffer
    
    	dstAddr.addrMode = (afAddrMode_t)zdlcDstAddr.addrMode;
            dstAddr.addr.shortAddr = zdlcDstAddr.addr.shortAddr;
            dstAddr.endPoint = zdlcDstAddr.endpoint;
            dstAddr.panId = zdlcDstAddr.panID;
    	
    	zcl_SendWrite(DLCSAPP_EP, &dstAddr, ZCL_CLUSTER_ID_GEN_BASIC, writeCmd, ZCL_FRAME_CLIENT_SERVER_DIR, 0, 0);
    }

  • Your code looks fine so I suspect the problem is destination address.
  • Hi YiKai,

    With your kindly suggestion, I can modify light side location desc as I wish.

    One more question, 

    I want to verify read attribute function. I already added code at switch side to read attribute of light side.

    At light side, I set breakpoint at zclProcessInReadCmd (zcl.c), when switch trigger read attribute action I can receive read command from switch.

    and in zclProcessInReadCmd function light finally will call zcl_SendReadRsp to send read resp command to switch side.

    How should I check read rsp command at switch side ?

  • You can check read rsp in zclSampleSw_ProcessInReadRspCmd.
  • Hi, YiKai

    At switch side, I am using cc2630EM, 

    In switch.c file, I cannot find relative callback function to catch read resp command.

  • If you use CC2630EM, it is in zclParseInReadRspCmd.

  • Hi YiKai.
    zclProcessInReadCmd shoule be called back when switch receive read cmd from light side.
    plz help me to double check
  • Sorry, it is zclParseInReadRspCmd().
  • how should I use the received read value using in my app source file (maybe switch.c).

    Thanks
  • I don't see related registration process like that for CC2530. I will dig into it and see if there is any similar function for C26xx.