Closed jkano closed 2 weeks ago
Also, just for testing, I changed the behavior to send a esp_zb_zdo_ieee_addr_req()
to get the ieee address knowing the short address. I know the nwk address of both the devices.
This is the code:
static void ieee_addr_req_cb(esp_zb_zdp_status_t zdo_status, esp_zb_ieee_addr_t ieee_addr, void *user_ctx)
{
ESP_LOGI(TAG, "ieee_addr_req_cb(), status: %02x", zdo_status);
if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS)
{
ESP_LOGI(TAG, "got ieee addr: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
ieee_addr[7], ieee_addr[6], ieee_addr[5],
ieee_addr[4], ieee_addr[3], ieee_addr[2],
ieee_addr[1], ieee_addr[0]);
}
}
void button_cb(void)
{
ESP_LOGI(TAG, "Button pressed, sending ieee request");
esp_zb_zdo_ieee_addr_req_param_t ieee_req;
ieee_req.addr_of_interest = 0xbd29; <--- Here I tested with the device own short address and remote device short addr
ieee_req.dst_nwk_addr = 0;
ieee_req.request_type = ZB_ZDO_SINGLE_DEVICE_RESP;
ieee_req.start_index = 0;
ESP_LOGI(TAG, "ieee addr req for 0x%04x", ieee_req.addr_of_interest);
esp_zb_zdo_ieee_addr_req(&ieee_req, ieee_addr_req_cb, NULL);
}
And here are the logs:
I (23) boot: ESP-IDF v5.3.1 2nd stage bootloader
I (23) boot: compile time Oct 23 2024 21:37:15
I (24) boot: chip revision: v0.1
I (26) boot.esp32c6: SPI Speed : 80MHz
I (31) boot.esp32c6: SPI Mode : DIO
I (35) boot.esp32c6: SPI Flash Size : 8MB
. . .
I (00:15:16.280) APP: Started in zigbee mode
W (00:15:16.299) APP: Network (0x50de) closed, devices joining not allowed.
I (00:15:16.304) APP: Device is NOT factory reset, joined as 0xbd29
I (00:15:16.748) APP: Button pressed, sending ieee request
I (00:15:16.749) APP: ieee addr req for 0xbd29 <--- Here also tested with other device address which is 0xbf1c
I (00:15:16.868) APP: ieee_addr_req_cb(), status: 81
As you can see, requesting it's own nwk address results in a ESP_ZB_ZDP_STATUS_DEVICE_NOT_FOUND (also requested the other device nwk address and same result).
Also, I tested changing the addr_of_interest to the coordinator one (0x0000) and for it, the request works:
I (23) boot: ESP-IDF v5.3.1 2nd stage bootloader
I (23) boot: compile time Oct 23 2024 21:37:15
I (24) boot: chip revision: v0.1
I (26) boot.esp32c6: SPI Speed : 80MHz
I (31) boot.esp32c6: SPI Mode : DIO
I (35) boot.esp32c6: SPI Flash Size : 8MB
. . .
I (00:22:38.978) APP: Started in zigbee mode
W (00:22:38.996) APP: Network (0x50de) closed, devices joining not allowed.
I (00:22:39.001) APP: Device is NOT factory reset, joined as 0xbd29
I (00:22:39.446) APP: Button pressed, sending ieee request
I (00:22:39.446) APP: ieee addr req for 0x0000
I (00:22:39.593) APP: ieee_addr_req_cb(), status: 00
I (00:22:39.593) APP: got ieee addr: 00:15:8d:00:00:c3:87:03
So, I'm not sure what could be happening with these address requests to devices other than the coordinator.
Hi,
two devices with ieee: 0x00158d0000c39956 and 0x00158d00007c6e9e.
What is the type of these devices? Are they routers or end devices?
Additionally, what is the purpose of performing the above operation? It seems a bit unusual.
Hi, thanks for the reply.
Both devices are routers.
The use case is the following: The device we are building periodically sends a custom cluster command to all the devices in its binding table, making them do something. In the example I showed you, the periodic part was replaced with the button press, so I can try whenever I want.
But the binding table have the dst address (ieee) and the dst endpoint, so, to send the custom command I need the short address of those devices, so I first need to request the nwk addr and that’s what is not working now.
if there was a way to send a custom cluster command to a ieee address I could use that but I could not find a way to do that (even zboss API says it only supports short address).
@jkano ,
Both devices are routers.
The Zigbee device can only provide the zdo_nwk_addr
response for itself and its children. Therefore, if you attempt to get the nwk_addr
of a router from the coordinator, it will return ESP_ZB_ZDP_STATUS_DEVICE_NOT_FOUND
.
The device we are building periodically sends a custom cluster command to all the devices in its binding table, making them do something. In the example I showed you, the periodic part was replaced with the button press, so I can try whenever I want.
What command are you expecting to send? Based on the above description, the attribute reporting mechanism might be more suitable for your project. Please refer to the custom switch/light example.
if there was a way to send a custom cluster command to a ieee address I could use that but I could not find a way to do that (even zboss API says it only supports short address).
You can set the address_mode
of the custom command to either ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT
or ESP_ZB_APS_ADDR_MODE_64_PRESENT_ENDP_NOT_PRESENT
to send commands using the IEEE address.
Hi!
The Zigbee device can only provide the zdo_nwk_addr response for itself and its children. Therefore, if you attempt to get the nwk_addr of a router from the coordinator, it will return ESP_ZB_ZDP_STATUS_DEVICE_NOT_FOUND.
Oh I see.. gonna test this again changing the devices to be end devices to check.
What command are you expecting to send? Based on the above description, the attribute reporting mechanism might be more suitable for your project. Please refer to the custom switch/light example.
Zigbee reporting have its constraints for the payload you can send, the command we are sending is a Custom Cluster command which has a custom payload with multiple values so reporting is not useful in this case.
You can set the address_mode of the custom command to either ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT or ESP_ZB_APS_ADDR_MODE_64_PRESENT_ENDP_NOT_PRESENT to send commands using the IEEE address.
I know I can use esp_zb_zcl_custom_cluster_cmd_req()
to send a custom cluster command, but our command has a fixed payload which is an array of different sized values, i.e. uint8_t, uint16_t, uint64_t, so we can't use the normal array types.
I tried to send the custom command like this:
// This test is just an example of a real payload, it contains a uint8_t, uint16_t, uint64_t
uint8_t test[] = {0x8D, 0x00, 0x01, 0xB2, 0x28, 0xBE, 0x01, 0x00, 0x01, 0x28, 0x11};
esp_zb_zcl_custom_cluster_cmd_req_t req_params = {
.zcl_basic_cmd.dst_endpoint = dst_ep,
.zcl_basic_cmd.src_endpoint = src_ep,
.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT,
.profile_id = ESP_ZB_AF_HA_PROFILE_ID,
.cluster_id = custom_cluster_id,
.custom_cmd_id = custom_cluster_cmd_id,
.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV,
};
// Here I use the coordinator ieee address to test
memcpy(req_params.zcl_basic_cmd.dst_addr_u.addr_long, coord_ieee, sizeof(esp_zb_ieee_addr_t));
req_params.data.value = test;
req_params.data.size = sizeof(test);
// Don't know which one to use so I set to invalid
req_params.data.type = ESP_ZB_ZCL_ATTR_TYPE_INVALID;
esp_zb_zcl_custom_cluster_cmd_req(&req_params);
But after sending this command, any of our devices receives it (tested by changing the ieee dst_addr).
So, instead of using the esp_zb_zcl_custom_cluster_cmd_req()
I used the zboss API to build the ZCL command manually like this:
ZB_ZCL_CONSTRUCT_SET_FRAME_CONTROL( ... );
cmd_ptr = zb_zcl_start_command_header( ... );
// Use ZB_ZCL_PACKET_PUT_DATAXX to add the payload
ZB_ZCL_PACKET_PUT_DATA8( ... );
ZB_ZCL_PACKET_PUT_DATA16( ... );
ZB_ZCL_PACKET_PUT_DATA8( ... );
ZB_ZCL_PACKET_PUT_DATA32( ... );
ZB_ZCL_PACKET_PUT_DATA64( ... );
// Send frame
esp_zb_lock_acquire(portMAX_DELAY);
esp_err_t err = zb_zcl_finish_and_send_packet(zbuf_id, cmd_ptr, (const zb_addr_u *)(const void *)(&(addr)),
dst_addr_mode, src_ep, dst_ep, profile_id,
cluster_id, NULL);
esp_zb_lock_release();
But this function zb_zcl_finish_and_send_packet()
in the documentation says:
// @param dst_addr_mode destination address mode (only @ref ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT and @ref ZB_APS_ADDR_MODE_16_ENDP_PRESENT are supported)
So I'm not sure how I can send a very custom ZCL cluster command to a device using its ieee address.
@jkano ,
Zigbee reporting have its constraints for the payload you can send, the command we are sending is a Custom Cluster command which has a custom payload with multiple values so reporting is not useful in this case.
Considering the above discussion, the application logic seems quite complex. You want to retrieve the remote device's address from the binding table, which implies that remote devices are already aware of the current device’s address and need to send a bind_req()
to it. Then, you would retrieve the short address of the remote devices with zdo_nwk_req()
and ultimately send messages using that short address.
However, there might be a simpler approach. If the current device receives the bind_req()
, it should also have access to the remote device’s short address. You could use esp_zb_address_short_by_ieee()
to obtain this address directly.
Additionally, it seems there might be a more straightforward way to get the remote device’s address. Could you share the reason for obtaining it from the binding table? If possible, please consider closing this issue and opening a separate issue to discuss the background and design logic of your project for further clarification.
Hi, I already found a way to send the custom ZCL command, by sending to myself a esp_zb_zdo_binding_table_req()
to get the list of devices in the binding table and then using esp_zb_zcl_custom_cluster_cmd_req()
to send the custom ZCL command to each one of the devices on the binding table.
Btw, I used ESP_ZB_ZCL_ATTR_TYPE_SET
as the data type and added my custom payload, this way the command payload is just as I needed.
Thanks for the ideas. Closing as the main question was answered here:
@jkano ,
Both devices are routers.
The Zigbee device can only provide the
zdo_nwk_addr
response for itself and its children. Therefore, if you attempt to get thenwk_addr
of a router from the coordinator, it will returnESP_ZB_ZDP_STATUS_DEVICE_NOT_FOUND
.The device we are building periodically sends a custom cluster command to all the devices in its binding table, making them do something. In the example I showed you, the periodic part was replaced with the button press, so I can try whenever I want.
What command are you expecting to send? Based on the above description, the attribute reporting mechanism might be more suitable for your project. Please refer to the custom switch/light example.
if there was a way to send a custom cluster command to a ieee address I could use that but I could not find a way to do that (even zboss API says it only supports short address).
You can set the
address_mode
of the custom command to eitherESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT
orESP_ZB_APS_ADDR_MODE_64_PRESENT_ENDP_NOT_PRESENT
to send commands using the IEEE address.
Question
Hi, I'm trying to use the
esp_zb_zdo_nwk_addr_req()
to get the short address of all the devices currently in the binding table of my end device (esp32-c6). Im using library version 1.5.1.I have one coordinator, ieee: 0x00158d0000c38703, the esp32-c6 end device, ieee: 0x404ccafffe566270 and two devices with ieee: 0x00158d0000c39956 and 0x00158d00007c6e9e.
To do this at will, I added a button callback function,
button_cb
so when I press the button once I send the request for the binding table on the device and when I get the response, I iterate on all the entries of the binding table and request the short addresses of them:This is the part of my code that is involved:
I have previously added the coordinator to the binding table.
These are my logs:
Here I open the network for a new device to join:
Now, from my coordinator I send a bind request to this new device, to add it to the binding table.
Now I press the button again to send the requests:
As you can see, for the Coordinator (ieee: 0x00158d0000c38703) the request was ok and it got the nwk addr 0x0000 correctly but for the device that just joined (ieee: 0x00158d0000c39956, short: 0xbf1c) the status is ESP_ZB_ZDP_STATUS_DEVICE_NOT_FOUND.
Now I removed the device from the network and the binding table to add a new device, first opened the network and repeat the steps:
Here as you can see, I have the same behavior, for the coordinator it could get the short address but for the other device in the network it couldn't.
Do you know what I may be missing here of if this is a bug?
Thanks!
Additional context.
No response