Hello,
Setup:
nrf5340
ncs 2.9.1
Zigbee r23 add-on
I’ve implemented a custom ZCL cluster that acts as a data pipe. I’m trying to determine what the actual maximum payload size is for a ZCL command and whether APS fragmentation is functiona
Based on ZBOSS documentation, I believe I should be able to send roughly 8 APS fragments × ~80 bytes per APS payload ≈ ~640 bytes. As far as I know, APS fragmentation is automatic and does not require any Kconfig options.
In this ticket from 2 years ago: [Zigbee] ZCL Tunneling cluster / APS Fragmentation
In that thread, the poster found the maximum working payload was 52 bytes, and a Nordic engineer commented that “APS fragmentation won’t work.”
The thread did not end with a resolution.
In testing with my own configuration I've found that:
-
Using
zb_buf_get_out, max working payload: 52 bytes -
Using
zb_buf_get_out_delayed_ext, max working payload: ~79 bytes (which matches expected APS single-frame MTU under security) -
Sending > ~79 bytes:
-
zb_zcl_finish_and_send_packet_new()returnsRET_OK -
No frame is ever transmitted
-
No error callback or logs
-
-
Sending 256 bytes (requires APS fragmentation):
-
ZBOSS fatal error inside the stack
-
These results match the symptoms described in the older thread, which suggested APS fragmentation may not be functional.
My question:
Is APS fragmentation expected to work in the Zigbee R23 add-on for NCS 2.9.1 on nRF5340?
If so, is there any configuration required to enable it?
Or is this a known limitation of the current ZBOSS integration?
Here is the relevant part my implementation:
static void construct_command_frame(void)
{
AppCommand_t *cmd = &app_ctx.command;
app_ctx.sequence_number = ZCL_CTX().seq_number;
app_ctx.packet_info.ptr =
ZB_ZCL_START_PACKET_REQ(app_ctx.packet_info.buffer)
ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(
app_ctx.packet_info.ptr,
cmd->default_response)
ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(
app_ctx.packet_info.ptr,
ZB_ZCL_GET_SEQ_NUM(),
cmd->command_id);
for (zb_uint8_t i = 0; i < cmd->payload_length; i++)
{
ZB_ZCL_PACKET_PUT_DATA8(app_ctx.packet_info.ptr, cmd->payload[i]);
}
}
static void send_command_frame(zb_uint8_t bufid)
{
zb_ret_t zb_err_code;
AppZclPacketInfo_t *packet_info = &app_ctx.packet_info;
packet_info->buffer = bufid;
construct_command_frame();
zb_err_code = zb_zcl_finish_and_send_packet_new(
packet_info->buffer,
packet_info->ptr,
&packet_info->destination_addr,
packet_info->destination_addr_mode,
packet_info->destination_endpoint,
packet_info->source_endpoint,
packet_info->profile_id,
packet_info->cluster_id,
NULL,
0,
packet_info->disable_aps_ack,
0);
if (zb_err_code != RET_OK)
{
LOG_ERR("Can not send ZCL frame");
zb_osif_disable_all_inter();
zb_buf_free(packet_info->buffer);
zb_osif_enable_all_inter();
}
}
AppReturnCode_t Zigbee_SendCustomResponse(uint8_t *payload, size_t payload_length)
{
AppReturnCode_t errCode = AppReturnCode_Success;
zb_bufid_t bufid;
AppCommand_t *cmd;
AppZclPacketInfo_t *packet_info;
cmd = &app_ctx.command;
packet_info = &app_ctx.packet_info;
memcpy(cmd->payload, payload, payload_length);
cmd->payload_length = payload_length;
packet_info->source_endpoint = GENERIC_ENDPOINT;
packet_info->disable_aps_ack = ZB_FALSE;
zb_ret_t err = zb_buf_get_out_delayed_ext(send_command_frame,
0,
cmd->payload_length);
require_action(err == RET_OK, exit, errCode = AppReturnCode_NoResources);
exit:
return errCode;
}
Please let me know if you need any additional context or information to provide assistance.
Thanks,
Logan