How to get commands generated from client cluster in coordinator

Hello, I have a question about how to get commands generated from a client cluster in a coordinator. I am currently developing a hub to control and retrieve data from home appliances that support the Zigbee protocol.
This hub is equipped with nRF5340 and has Flash firmware built with nRF Connect SDK. I'm thinking of connecting a Hue Dimmer switch to this hub and using the hub to get information about the commands generated when the On/Off and Level Control switches are operated from the switch.

I have found that if I bind the On/Off cluster or Level Control cluster of Dimmer switches to the hub with "zdo bind on", I can get a log like below on the hub side as info level logs.

[03:57:54.107,513] <inf> zigbee.eprxzcl: Received ZCL command (15): src_addr=0x2ad3(short) src_ep=1 dst_ep=64 cluster_id=0x0006 profile_id=0x0104 cmd_dir=0 common_cmd=0 cmd_id=0x40 cmd_seq=1 disable_def_resp=0 manuf_code=void payload=[0000] (15)

My question is as follows.
1. Is this log defined in a callback function that is called when the hub gets a command? Where is that callback function defined?
2. Is there a correct way to use "zdo bind on" to retrieve information about a command? I would like to know if there is an easier way to get information about the command.

I am new to development using nRF5340, so I would appreciate any supportive information you can give me.

Parents
  • Hi,

    Just to add to my colleague's response.

    1. Is this log defined in a callback function that is called when the hub gets a command? Where is that callback function defined?

    The logs you refer to come from zigbee_logger_eprxzcl_ep_handler(). This is the endpoint logger, which parses and logs incoming ZCL frames. You can read more about this in Configuring Zigbee endpoint logger. As described there, you can set endpoint handlers with ZB_AF_SET_ENDPOINT_HANDLER().

    2. Is there a correct way to use "zdo bind on" to retrieve information about a command? I would like to know if there is an easier way to get information about the command.

    Can you clarify your goal? Do you want the nRF5340 to retrieve information about ZCL commands that are sent specifically to the nRF5340, or commands that are sent on the network in general? What kind of information do you want to retrieve?

    Best regards,
    Marte

  • Thanks for the helpful info.

    Can you clarify your goal? Do you want the nRF5340 to retrieve information about ZCL commands that are sent specifically to the nRF5340, or commands that are sent on the network in general? What kind of information do you want to retrieve?

    The goal is to be able to receive commands in general. I would like to get the eui64, cluster ID, command ID, and payload information for the device sending the command. For example, I would like to achieve the following.
    I have multiple Dimmer switches in my house and I want to know at the hub which switch sent which command and with what payload.

Reply
  • Thanks for the helpful info.

    Can you clarify your goal? Do you want the nRF5340 to retrieve information about ZCL commands that are sent specifically to the nRF5340, or commands that are sent on the network in general? What kind of information do you want to retrieve?

    The goal is to be able to receive commands in general. I would like to get the eui64, cluster ID, command ID, and payload information for the device sending the command. For example, I would like to achieve the following.
    I have multiple Dimmer switches in my house and I want to know at the hub which switch sent which command and with what payload.

Children
  • Hi,

    Here is an example of a handpoint handler that prints the IEEE address, cluster ID, command ID, and payload. You can modify it to fit your requirements.

    #define IEEE_ADDR_BUF_SIZE 17
    
    zb_uint8_t zb_nwk_coordinator_ep_handler(zb_bufid_t bufid)
    {
    	zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(bufid, zb_zcl_parsed_hdr_t);
    	size_t payload_length = zb_buf_len(bufid);
    	const zb_uint8_t *payload = zb_buf_begin(bufid);
    
    	zb_uint16_t short_addr;
    	zb_ieee_addr_t ieee_addr;
    	
    	switch (ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.addr_type) {
    	case ZB_ZCL_ADDR_TYPE_SHORT:
    		short_addr = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr;
    		zb_address_ieee_by_short(short_addr, ieee_addr);
    		break;
    	case ZB_ZCL_ADDR_TYPE_IEEE:
    		ZB_IEEE_ADDR_COPY(ieee_addr, ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.ieee_addr);
    		short_addr = zb_address_short_by_ieee(ieee_addr);
    		break;
    	}
    
    	char ieee_addr_str[IEEE_ADDR_BUF_SIZE] = { 0 };
    	char payload_str[255];
    	ieee_addr_to_str(ieee_addr_str, IEEE_ADDR_BUF_SIZE, ieee_addr);
    	to_hex_str(payload_str, sizeof(payload_str), payload, payload_length, false);
    
    	LOG_INF("Received ZCL cmd: IEEE_src_addr=%s, cluster_id=0x%04x, cmd_id=0x%02x, payload=[%s]", 
    						ieee_addr_str, 
    						cmd_info->cluster_id,
    						cmd_info->cmd_id,
    						payload_str);
    
    	return 0;
    }

    I have tested this in the network coordinator sample. Make sure to register the endpoint handler after registering the device context like this:

    ZB_AF_REGISTER_DEVICE_CTX(&nwk_coordinator);
    ZB_AF_SET_ENDPOINT_HANDLER(ZIGBEE_COORDINATOR_ENDPOINT, zb_nwk_coordinator_ep_handler);

    Best regards,
    Marte

Related