BLOB Transfer Client

The Binary Large Object (BLOB) Transfer Client is the sender of the BLOB transfer. It supports sending BLOBs of any size to any number of Target nodes, in both Push BLOB Transfer Mode and Pull BLOB Transfer Mode.



The BLOB Transfer Client is instantiated on an element with a set of event handler callbacks:

static const struct bt_mesh_blob_cli_cb blob_cb = {
      /* Callbacks */

static struct bt_mesh_blob_cli blob_cli = {
      .cb = &blob_cb,

static struct bt_mesh_model models[] = {

Transfer context

Both the transfer capabilities retrieval procedure and the BLOB transfer uses an instance of a bt_mesh_blob_cli_inputs to determine how to perform the transfer. The BLOB Transfer Client Inputs structure must at least be initialized with a list of targets, an application key and a time to live (TTL) value before it is used in a procedure:

static struct bt_mesh_blob_target targets[3] = {
        { .addr = 0x0001 },
        { .addr = 0x0002 },
        { .addr = 0x0003 },
static struct bt_mesh_blob_cli_inputs inputs = {
        .app_idx = MY_APP_IDX,
        .ttl = BT_MESH_TTL_DEFAULT,

sys_slist_append(&inputs.targets, &targets[0].n);
sys_slist_append(&inputs.targets, &targets[1].n);
sys_slist_append(&inputs.targets, &targets[2].n);

Note that all BLOB Transfer Servers in the transfer must be bound to the chosen application key.

Group address

The application may additionally specify a group address in the context structure. If the group is not BT_MESH_ADDR_UNASSIGNED, the messages in the transfer will be sent to the group address, instead of being sent individually to each Target node. Mesh Manager must ensure that all Target nodes having the BLOB Transfer Server model subscribe to this group address.

Using group addresses for transferring the BLOBs can generally increase the transfer speed, as the BLOB Transfer Client sends each message to all Target nodes at the same time. However, sending large, segmented messages to group addresses in Bluetooth mesh is generally less reliable than sending them to unicast addresses, as there is no transport layer acknowledgment mechanism for groups. This can lead to longer recovery periods at the end of each block, and increases the risk of losing Target nodes. Using group addresses for BLOB transfers will generally only pay off if the list of Target nodes is extensive, and the effectiveness of each addressing strategy will vary heavily between different deployments and the size of the chunks.

Transfer timeout

If a Target node fails to respond to an acknowledged message within the BLOB Transfer Client’s time limit, the Target node is dropped from the transfer. The application can reduce the chances of this by giving the BLOB Transfer Client extra time through the context structure. The extra time may be set in 10-second increments, up to 182 hours, in addition to the base time of 20 seconds. The wait time scales automatically with the transfer TTL.

Note that the BLOB Transfer Client only moves forward with the transfer in following cases:

  • All Target nodes have responded.

  • A node has been removed from the list of Target nodes.

  • The BLOB Transfer Client times out.

Increasing the wait time will increase this delay.

BLOB transfer capabilities retrieval

It is generally recommended to retrieve BLOB transfer capabilities before starting a transfer. The procedure populates the transfer capabilities from all Target nodes with the most liberal set of parameters that allows all Target nodes to participate in the transfer. Any Target nodes that fail to respond, or respond with incompatible transfer parameters, will be dropped.

Target nodes are prioritized according to their order in the list of Target nodes. If a Target node is found to be incompatible with any of the previous Target nodes, for instance by reporting a non-overlapping block size range, it will be dropped. Lost Target nodes will be reported through the lost_target callback.

The end of the procedure is signalled through the caps callback, and the resulting capabilities can be used to determine the block and chunk sizes required for the BLOB transfer.

BLOB transfer

The BLOB transfer is started by calling bt_mesh_blob_cli_send() function, which (in addition to the aforementioned transfer inputs) requires a set of transfer parameters and a BLOB stream instance. The transfer parameters include the 64-bit BLOB ID, the BLOB size, the transfer mode, the block size in logarithmic representation and the chunk size. The BLOB ID is application defined, but must match the BLOB ID the BLOB Transfer Servers have been started with.

The transfer runs until it either completes successfully for at least one Target node, or it is cancelled. The end of the transfer is communicated to the application through the end callback. Lost Target nodes will be reported through the lost_target callback.

API reference

group bt_mesh_blob_cli



BLOB Transfer Client model Composition Data entry.



enum bt_mesh_blob_cli_state

BLOB Transfer Client state.



No transfer is active.


Retrieving transfer capabilities.


Sending transfer start.


Sending block start.


Sending block chunks.


Checking block status.


Checking transfer status.


Cancelling transfer.


Transfer is suspended.


Checking transfer progress.


int bt_mesh_blob_cli_caps_get(struct bt_mesh_blob_cli *cli, const struct bt_mesh_blob_cli_inputs *inputs)

Retrieve transfer capabilities for a list of Target nodes.

Queries the availability and capabilities of all Target nodes, producing a cumulative set of transfer capabilities for the Target nodes, and returning it through the bt_mesh_blob_cli_cb::caps callback.

Retrieving the capabilities may take several seconds, depending on the number of Target nodes and mesh network performance. The end of the procedure is indicated through the bt_mesh_blob_cli_cb::caps callback.

This procedure is not required, but strongly recommended as a preparation for a transfer to maximize performance and the chances of success.

  • cli – BLOB Transfer Client instance.

  • inputs – Statically allocated BLOB Transfer Client transfer inputs.


0 on success, or (negative) error code otherwise.

int bt_mesh_blob_cli_send(struct bt_mesh_blob_cli *cli, const struct bt_mesh_blob_cli_inputs *inputs, const struct bt_mesh_blob_xfer *xfer, const struct bt_mesh_blob_io *io)

Perform a BLOB transfer.

Starts sending the transfer to the Target nodes. Only Target nodes with a status of BT_MESH_BLOB_SUCCESS will be considered.

The transfer will keep going either until all Target nodes have been dropped, or the full BLOB has been sent.

The BLOB transfer may take several minutes, depending on the number of Target nodes, size of the BLOB and mesh network performance. The end of the transfer is indicated through the bt_mesh_blob_cli_cb::end callback.

A Client only supports one transfer at the time.

  • cli – BLOB Transfer Client instance.

  • inputs – Statically allocated BLOB Transfer Client transfer inputs.

  • xfer – Statically allocated transfer parameters.

  • io – BLOB stream to read the transfer from.


0 on success, or (negative) error code otherwise.

int bt_mesh_blob_cli_suspend(struct bt_mesh_blob_cli *cli)

Suspend the active transfer.

  • cli – BLOB Transfer Client instance.


0 on success, or (negative) error code otherwise.

int bt_mesh_blob_cli_resume(struct bt_mesh_blob_cli *cli)

Resume the suspended transfer.

  • cli – BLOB Transfer Client instance.


0 on success, or (negative) error code otherwise.

void bt_mesh_blob_cli_cancel(struct bt_mesh_blob_cli *cli)

Cancel an ongoing transfer.

  • cli – BLOB Transfer Client instance.

int bt_mesh_blob_cli_xfer_progress_get(struct bt_mesh_blob_cli *cli, const struct bt_mesh_blob_cli_inputs *inputs)

Get the progress of BLOB transfer.

This function can only be used if the BLOB Transfer Client is currently not performing a BLOB transfer. To get progress of the active BLOB transfer, use the bt_mesh_blob_cli_xfer_progress_active_get function.

  • cli – BLOB Transfer Client instance.

  • inputs – Statically allocated BLOB Transfer Client transfer inputs.


0 on success, or (negative) error code otherwise.

uint8_t bt_mesh_blob_cli_xfer_progress_active_get(struct bt_mesh_blob_cli *cli)

Get the current progress of the active transfer in percent.

  • cli – BLOB Transfer Client instance.


The current transfer progress, or 0 if no transfer is active.

bool bt_mesh_blob_cli_is_busy(struct bt_mesh_blob_cli *cli)

Get the current state of the BLOB Transfer Client.

  • cli – BLOB Transfer Client instance.


true if the BLOB Transfer Client is currently participating in a transfer or retrieving the capabilities and false otherwise.

struct bt_mesh_blob_target_pull
#include <blob_cli.h>

Target node’s Pull mode (Pull BLOB Transfer Mode) context used while sending chunks to the Target node.

Public Members

int64_t block_report_timestamp

Timestamp when the Block Report Timeout Timer expires for this Target node.


Missing chunks reported by this Target node.

struct bt_mesh_blob_target
#include <blob_cli.h>

BLOB Transfer Client Target node.

Public Members

sys_snode_t n

Linked list node.

uint16_t addr

Target node address.

struct bt_mesh_blob_target_pull *pull

Target node’s Pull mode context.

Needs to be initialized when sending a BLOB in Pull mode.

uint8_t status

BLOB transfer status, see bt_mesh_blob_status.

struct bt_mesh_blob_xfer_info
#include <blob_cli.h>

BLOB transfer information.

If phase is BT_MESH_BLOB_XFER_PHASE_INACTIVE, the fields below phase are not initialized. If phase is BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_START, the fields below id are not initialized.

Public Members

enum bt_mesh_blob_status status

BLOB transfer status.

enum bt_mesh_blob_xfer_mode mode

BLOB transfer mode.

enum bt_mesh_blob_xfer_phase phase

BLOB transfer phase.

uint64_t id


uint32_t size

BLOB size in octets.

uint8_t block_size_log

Logarithmic representation of the block size.

uint16_t mtu_size

MTU size in octets.

const uint8_t *missing_blocks

Bit field indicating blocks that were not received.

struct bt_mesh_blob_cli_inputs
#include <blob_cli.h>

BLOB Transfer Client transfer inputs.

Public Members

sys_slist_t targets

Linked list of Target nodes.

Each node should point to bt_mesh_blob_target::n.

uint16_t app_idx

AppKey index to send with.

uint16_t group

Group address destination for the BLOB transfer, or BT_MESH_ADDR_UNASSIGNED to send every message to each Target node individually.

uint8_t ttl

Time to live value of BLOB transfer messages.

uint16_t timeout_base

Additional response time for the Target nodes, in 10-second increments.

The extra time can be used to give the Target nodes more time to respond to messages from the Client. The actual timeout will be calculated according to the following formula:

*  timeout = 20 seconds + (10 seconds * timeout_base) + (100 ms * TTL)

If a Target node fails to respond to a message from the Client within the configured transfer timeout, the Target node is dropped.

struct bt_mesh_blob_cli_caps
#include <blob_cli.h>

Transfer capabilities of a Target node.

Public Members

size_t max_size

Max BLOB size.

uint8_t min_block_size_log

Logarithmic representation of the minimum block size.

uint8_t max_block_size_log

Logarithmic representation of the maximum block size.

uint16_t max_chunks

Max number of chunks per block.

uint16_t max_chunk_size

Max chunk size.

uint16_t mtu_size

Max MTU size.

enum bt_mesh_blob_xfer_mode modes

Supported transfer modes.

struct bt_mesh_blob_cli_cb
#include <blob_cli.h>

Event handler callbacks for the BLOB Transfer Client model.

All handlers are optional.

Public Members

void (*caps)(struct bt_mesh_blob_cli *cli, const struct bt_mesh_blob_cli_caps *caps)

Capabilities retrieval completion callback.

Called when the capabilities retrieval procedure completes, indicating that a common set of acceptable transfer parameters have been established for the given list of Target nodes. All compatible Target nodes have status code BT_MESH_BLOB_SUCCESS.

Param cli:

BLOB Transfer Client instance.

Param caps:

Safe transfer capabilities if the transfer capabilities of at least one Target node has satisfied the Client, or NULL otherwise.

void (*lost_target)(struct bt_mesh_blob_cli *cli, struct bt_mesh_blob_target *target, enum bt_mesh_blob_status reason)

Target node loss callback.

Called whenever a Target node has been lost due to some error in the transfer. Losing a Target node is not considered a fatal error for the Client until all Target nodes have been lost.

Param cli:

BLOB Transfer Client instance.

Param target:

Target node that was lost.

Param reason:

Reason for the Target node loss.

void (*suspended)(struct bt_mesh_blob_cli *cli)

Transfer is suspended.

Called when the transfer is suspended due to response timeout from all Target nodes.

Param cli:

BLOB Transfer Client instance.

void (*end)(struct bt_mesh_blob_cli *cli, const struct bt_mesh_blob_xfer *xfer, bool success)

Transfer end callback.

Called when the transfer ends.

Param cli:

BLOB Transfer Client instance.

Param xfer:

Completed transfer.

Param success:

Status of the transfer. Is true if at least one Target node received the whole transfer.

void (*xfer_progress)(struct bt_mesh_blob_cli *cli, struct bt_mesh_blob_target *target, const struct bt_mesh_blob_xfer_info *info)

Transfer progress callback.

The content of info is invalidated upon exit from the callback. Therefore it needs to be copied if it is planned to be used later.

Param cli:

BLOB Transfer Client instance.

Param target:

Target node that responded to the request.

Param info:

BLOB transfer information.

void (*xfer_progress_complete)(struct bt_mesh_blob_cli *cli)

End of Get Transfer Progress procedure.

Called when all Target nodes have responded or the procedure timed-out.

Param cli:

BLOB Transfer Client instance.

struct bt_mesh_blob_cli
#include <blob_cli.h>

BLOB Transfer Client model instance.

Public Members

const struct bt_mesh_blob_cli_cb *cb

Event handler callbacks.