Is there any reason not to implement an bluetooth-mesh BLOB Transfer sample?

When I first created the BLOB Transfer model, I had to analysis the DFU sample code because there was no BLOB Transfer model sample.

Is it possible for me to create a sample and contribute it to the sdk-nrf if possible?
If possible, can I create a sample of the ctl model and contribute to it as well? Or are there any restrictions?

Parents Reply Children
  • Hi rich.rarey,

    This is just from a DFU sample, but it might be a little challenging for someone new to BLOB Transfer and DFU.

    I only took out the BLOB Transfer Server from the DFU target. I can share it if you want.

  • Yes please, TOT0Ro, I would like to see it. My interest is moving arbitrary binary data around a mesh, unrelated to DFU.

  • Here!

    It might be important to look at line 192. You can use it as a replacement for the DFU target sample main.c.

    /** @file
     *  @brief Bluetooth Mesh BLOB Transfer Server role sample
     */
    #include <zephyr/kernel.h>
    #include <bluetooth/mesh/dk_prov.h>
    #include <zephyr/storage/flash_map.h>
    #include <dk_buttons_and_leds.h>
    #include <zephyr/bluetooth/bluetooth.h>
    #include <zephyr/bluetooth/mesh.h>
    #include "dfu_target.h"
    
    #include <zephyr/logging/log.h>
    LOG_MODULE_DECLARE(settings, CONFIG_SETTINGS_LOG_LEVEL);
    
    #define BLOB_ID 0xDEADBEEFDEADBEEF
    
    //static struct bt_mesh_blob_io_flash dfu_flash_stream;
    static struct bt_mesh_blob_io_flash blob_flash_stream;
    static int blob_xfer_start(struct bt_mesh_blob_srv *srv, struct bt_mesh_msg_ctx *ctx,
    		     struct bt_mesh_blob_xfer *xfer);
    static void blob_xfer_end(struct bt_mesh_blob_srv *srv, uint64_t id, bool success);
    static void blob_xfer_suspended(struct bt_mesh_blob_srv *srv);
    static void blob_xfer_resume(struct bt_mesh_blob_srv *srv);
    static int blob_xfer_recover(struct bt_mesh_blob_srv *srv,
    		       struct bt_mesh_blob_xfer *xfer,
    		       const struct bt_mesh_blob_io **io);
    
    /* Set up a repeating delayed work to blink the DK's LEDs when attention is
     * requested.
     */
    static struct k_work_delayable attention_blink_work;
    static bool attention;
    
    static void attention_blink(struct k_work *work)
    {
    	static int idx;
    	const uint8_t pattern[] = {
    #if DT_NODE_EXISTS(DT_ALIAS(led0))
    		BIT(0),
    #endif
    #if DT_NODE_EXISTS(DT_ALIAS(led1))
    		BIT(1),
    #endif
    #if DT_NODE_EXISTS(DT_ALIAS(led2))
    		BIT(2),
    #endif
    #if DT_NODE_EXISTS(DT_ALIAS(led3))
    		BIT(3),
    #endif
    	};
    
    	if (attention) {
    		dk_set_leds(pattern[idx++ % ARRAY_SIZE(pattern)]);
    		k_work_reschedule(&attention_blink_work, K_MSEC(30));
    	} else {
    		dk_set_leds(DK_NO_LEDS_MSK);
    	}
    }
    
    static void attention_on(const struct bt_mesh_model *mod)
    {
    	attention = true;
    	k_work_reschedule(&attention_blink_work, K_NO_WAIT);
    }
    
    static void attention_off(const struct bt_mesh_model *mod)
    {
    	/* Will stop rescheduling blink timer */
    	attention = false;
    }
    
    static const struct bt_mesh_health_srv_cb health_srv_cb = {
    	.attn_on = attention_on,
    	.attn_off = attention_off,
    };
    
    static struct bt_mesh_health_srv health_srv = {
    	.cb = &health_srv_cb,
    };
    
    BT_MESH_HEALTH_PUB_DEFINE(health_pub, 0);
    
    static const struct bt_mesh_blob_srv_cb blob_srv_cb = {
    	.start = blob_xfer_start,
    	.end = blob_xfer_end,
    	.suspended = blob_xfer_suspended,
    	.resume = blob_xfer_resume,
    	.recover = blob_xfer_recover,
    };
    
    static struct bt_mesh_blob_srv blob_srv = {
    	.cb = &blob_srv_cb,
    };
    
    static int blob_xfer_start(struct bt_mesh_blob_srv *srv, struct bt_mesh_msg_ctx *ctx,
    		     struct bt_mesh_blob_xfer *xfer)
    {
    	printk("BLOB Transfer Start!!\n");
    	return 0;
    }
    
    static void blob_xfer_end(struct bt_mesh_blob_srv *srv, uint64_t id, bool success)
    {
    	uint8_t **data;
    	int i;
    	size_t size;
    	if (success == 1){
    		printk("BLOB Transfer End: Success\n");
    		size = srv->state.xfer.size;
    		flash_area_read(blob_flash_stream.area, blob_flash_stream.offset, *data, size);
    		for (i=0; i<size; i++) {
    			printk("%02X", (*data)[i]);
    		}
    		printk("\n");
    	}
    	else {
    		printk("BLOB Transfer End: Failed\n");
    	}
    	//bt_mesh_blob_srv_recv(&blob_srv, 0xDEADBEEFDEADBEEF, &blob_flash_stream.io, 0xFF, 2);
    }
    
    static void blob_xfer_suspended(struct bt_mesh_blob_srv *srv)
    {
    	printk("BLOB Transfer Suspended!!\n");
    }
    static void blob_xfer_resume(struct bt_mesh_blob_srv *srv)
    {
    	printk("BLOB Transfer Resume\n");
    }
    static int blob_xfer_recover(struct bt_mesh_blob_srv *srv,
    		       struct bt_mesh_blob_xfer *xfer,
    		       const struct bt_mesh_blob_io **io)
    {
    	//*io = &blob_flash_stream.io;
    	printk("BLOB Transfer Recover\n");
    	return 0;
    }
    
    static struct bt_mesh_model models[] = {
    	BT_MESH_MODEL_CFG_SRV,
    	BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
    	BT_MESH_MODEL_DFU_SRV(&dfu_srv)
    };
    
    static struct bt_mesh_model models2[] = {
    	BT_MESH_MODEL_BLOB_SRV(&blob_srv)
    };
    
    static struct bt_mesh_elem elements[] = {
    	BT_MESH_ELEM(1, models, BT_MESH_MODEL_NONE),
    	BT_MESH_ELEM(2, models2, BT_MESH_MODEL_NONE),
    };
    
    static const struct bt_mesh_comp comp = {
    	.cid = CONFIG_BT_COMPANY_ID,
    	.elem = elements,
    	.elem_count = ARRAY_SIZE(elements),
    };
    
    static void bt_ready(int err)
    {
    	if (err) {
    		printk("Bluetooth init failed (err %d)\n", err);
    		return;
    	}
    
    	printk("Bluetooth initialized\n");
    
    	dk_leds_init();
    
    	printk("B\n");
    	err = bt_mesh_init(bt_mesh_dk_prov_init(), &comp);
    	if (err) {
    		printk("Initializing mesh failed (err %d)\n", err);
    		return;
    	}
    
    	printk("C\n");
    	LOG_ERR("C\n");
    	if (IS_ENABLED(CONFIG_SETTINGS)) {
    		settings_load();
    	}
    
    	LOG_ERR("D\n");
    	bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT);
    
    	printk("Mesh initialized\n");
    
    	/* Confirm the image and mark it as applied after the mesh started. */
    	dfu_target_image_confirm();
    	
    	bt_mesh_blob_srv_recv(&blob_srv, BLOB_ID, &blob_flash_stream.io, 0xFF, 2);
    
    	printk("Complete bt_ready\n");
    }
    
    int main(void)
    {
    	int err;
    
    	printk("Initializing...\n");
    
    	// err = bt_mesh_blob_io_flash_init(&dfu_flash_stream, FIXED_PARTITION_ID(slot1_partition),
    	// 				 0);
    	// if (err) {
    	// 	printk("Failed to init BLOB IO Flash module: %d\n", err);
    	// 	return 1;
    	// }
    	err = bt_mesh_blob_io_flash_init(&blob_flash_stream, FIXED_PARTITION_ID(slot1_partition),
    					 0);
    	if (err) {
    		printk("Failed to init BLOB IO Flash module: %d\n", err);
    		return 1;
    	}
    
    	k_work_init_delayable(&attention_blink_work, attention_blink);
    	dfu_target_init(&blob_flash_stream);
    
    	err = bt_enable(bt_ready);
    	if (err) {
    		printk("Bluetooth init failed (err %d)\n", err);
    		return 1;
    	}
    
    	return 0;
    }
    

Related