CoAP Block-wise Transfer over OpenThread (tested via OT-CLI)

I’m trying to transmit a payload of up to 2,450 bytes using CoAP over OpenThread. Before jumping into firmware development, I want to evaluate the feasibility of transmitting large payloads using the OT-CLI sample.

As a starting point, let me clarify that my CoAP server is up and running. To obtain the synthesized IPv6 address from the OTBR, I run:

$ ot dns resolve4 <CoAP server IPv4>

1) Standard transmission (non-block-wise transmission)

When I transmit short payloads using:

$ ot coap put <synthesized IPv6 address> <uri> con {"test":123} 

I can see the data arriving at the CoAP server, and I also receive the corresponding ACK on my OpenThread device running the OT-CLI sample.

To evaluate the transmission of a payload of up to 2,450 bytes, I used the OT-CLI sample with the following command:

$ ot coap put <synthesized IPv6 address> <uri> con <payload> 

where <payload> is a 2,450-byte JSON payload. However, I noticed that the command input appears to be limited to approximately 415 bytes.

I then inspected the OT-CLI sample and found that there is a Kconfig parameter in the prj.conf file that limits the maximum length of shell commands. I increased this limit and rebuilt the sample:

CONFIG_SHELL_ARGC_MAX=26
CONFIG_SHELL_CMD_BUFF_SIZE=2600

After this change, the entire command appears to be accepted, but I now get the following error:

Error 6: Parse 

What does this error mean? Is it actually possible to use the OT-CLI command with payloads of this size?

2) Block-wise transmission 

To further evaluate the feasibility of transmitting large payloads over CoAP with OpenThread, I looked into the block-wise transfer implementation, since this is the recommended approach for large payloads to avoid IPv6 fragmentation due to the small MTU size of IEEE 802.15.4. Since I need to send a payload of up to 2,450 bytes, using a block size of 64 bytes would require transmitting approximately 40 blocks.

To test this, I used the following command:

$ ot coap put <synthesized IPv6 address> <uri> block-64 40

From the documentation, this command will transmit 40 data blocks of 64 bytes each to the CoAP server. However, no payload ever arrives at my CoAP server. From the Graylog logs, it appears that the server is trying to parse the value 40 as the payload, even though in this command 40 is intended to represent the number of blocks to send, with the actual payload consisting of random bytes. Is the block-wise implementation in OT-CLI working as expected?

The documentation also states:

“The block- type requires OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE to be set.”

Do I need to enable this configuration? If so, can I do it in the prj.conf file like this?

CONFIG_OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE=y
Parents
  • Hi,

    I reproduced your issue with block-wise transfers and confirmed that the block count parameter was being treated as the payload.

    When building the sample, you are using the prebuilt OpenThread library, so the configuration changes are not applied. Block-wise CoAP is not enabled by default so it fails.

    To fix this:

    Enable block-wise CoAP support:
    CONFIG_OPENTHREAD_COAP_BLOCK=y

    This maps to:
    OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE

    Force OpenThread to rebuild by enabling:
    CONFIG_OPENTHREAD_SOURCES=y

    After enabling both options and rebuilding, block-wise transfers work correctly. I was able to send a request successfully using:

    ot coap post <synthesized IPv6 address> <uri> block-64 8


    For the last question. You should rely on the Zephyr CoAP API as described in these docs, this requires no changes as this is the default. The docs also describes the pros and cons of each approach.

    Best regards,
    Benjamin

  • Hi,

    Thank you for the effort and guidance — I really appreciate it. I’ll test this on my side and provide feedback shortly.

    Regarding your suggestion to use the Zephyr CoAP API, do you foresee any issues with combining the Zephyr CoAP API (using OpenThread as the transport layer) with direct OpenThread API calls?

    In my application, I infer the location of SED devices based on their parent router’s MAC address and cross-reference this information with a LUT that maps all Thread Router devices, their MAC addresses, and their physical locations. Consequently, one of the data fields included in the large payload (up to 2500 bytes) that the SED needs to transmit to the CoAP server via block-wise transfer is the MAC address of its OpenThread parent router, which I obtain through direct OpenThread API calls.

  • I need to correct myself. The default architecture in the CLI sample is the direct IEEE 802.15.4 radio integration with the OpenThread Stack, not the integration with Zephyr networking layer (L2). 

Reply Children
Related