Skip to content

Using CoAP Block Wise to transfer large file ?

Simon edited this page Jul 9, 2021 · 8 revisions

One of the frequent asked question is about how using Leshan to download firmware package?

Specifications says :

Basic CoAP messages work well for small payloads from sensors and actuators; however, applications will need to transfer larger payloads occasionally for instance, for firmware updates.
-- RFC 7959 - Block-Wise Transfers in the Constrained Application Protocol (CoAP)

A LwM2M Client MUST support block-wise transfer [CoAP_Blockwise] if it implements the Firmware Update object.
A LwM2M Server MUST support block-wise transfer

-- The LWM2M specification v1.0 (§E.6 LwM2M Object: Firmware Update)

But in real world this is not that easy!

What is our recommended way?

In LWM2M there are 3 common ways to get the firmware package :

  1. Server sends package to client writing resource package(5/0/0), this will use CoAP(s) block1.
  2. Server sends a coap(s):// package URI to client writing package URI resource (5/0/1), then client get package using CoAP(s) block2.
  3. Server sends an http(s):// package URI to client writing package URI resource (5/0/1), then client get package using HTTP/HTTPS.

If you can we strongly advice to use the 3) HTTP/HTTPS way, because it should be the more reliable way.
If for some reasons you can not use it, we advice to fallback with 2) block2 solution.

What are problem using CoAP for large payload?

  1. This study talks a bit of CoAP blockwise transmission time over cellular networks : " Especially in the case of LTE the transmission time depends not only on the total amount of data, but also on the exact sequencing of data transfer. This has been clearly observed in the evaluation of CoAP. Its implementation of reliable data exchange is not suitable for the transmission of large payloads over cellular networks. Protocols based on TCP achieve a better performance due to TCP-features like windowing."
    (This is probably a CoAP limitation, this is mitigates by Achim Kraus Californium maintainer and so could be more a common implementation limitation)

  2. Comparison and Evaluation of LwM2M and MQTT in Low-Power Wide-Area Networks.pdf by Alessandro Parmigiani says that :
    "when sending single messages from client to server, MQTT outperforms LwM2M for large payload-transfer, consuming 20% less average energy. On the other hand, when maintaining packet lengths below LwM2M’s MTU, MQTT uses 44% more average energy." Large payload-transfer is the case where Block-Wwise transfer is used.
    (This is probably a CoAP limitation)

  3. Leshan is based on Californium. To handle block-Wise transfer, Leshan use the Californium transparent block mode which will buffer the whole content of the payload in memory until the transfer is complete. So this will consume a lot of RAM.
    (This is a Leshan limitation, as we could imagine to not use transparent block mode)

  4. block1 transfer does not support that address/port of a peer changes during transfer. In Dynamic IP environment (like NAT), this could be an issue causing to retry sending from scratch. Maybe dtls-connection-id draft will help for this.
    (Connection ID is now available in Californium and so usable in Leshan)

I want to use CoAP for large payload anyway.

If you are using the 2) block2 recommended way you will need a kind of CoAP File Transfer Resource.
There is nothing "ready to use"/"production ready" in Leshan/Californium ecosystem, but you can have a look at https://github.com/eclipse/leshan/issues/367.

If you want to add a kind of Californium CoAP File Transfer Resource directly to Leshan Server, you can do something like this :

LeshanServer lwServer = builder.build();
lwServer.coap().getServer().add(new MyFileServerResource());
lwServer.start();

You should also have a look at how timer is handled in Leshan/Californium.

You should also be aware of the some Californium properties about Block-Wise Transfert:

  • PREFERRED_BLOCK_SIZE
  • MAX_MESSAGE_SIZE
  • MAX_RESOURCE_BODY_SIZE
  • BLOCKWISE_STATUS_LIFETIME
  • BLOCKWISE_STRICT_BLOCK2_OPTION

in NetworkConfig which can be set using builder.setCoapConfig(NetworkConfig config).