<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>How to add mesh to BLE device</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/59364/how-to-add-mesh-to-ble-device</link><description>Hi, I am currently working on a project, where I am porting an existing application to the NRF52840. The porting of the functionality have been rather smooth, but i struggling now with adding MESH to my project and i wondoer if my use case is even possible</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Tue, 24 Mar 2020 13:12:02 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/59364/how-to-add-mesh-to-ble-device" /><item><title>RE: How to add mesh to BLE device</title><link>https://devzone.nordicsemi.com/thread/241385?ContentTypeID=1</link><pubDate>Tue, 24 Mar 2020 13:12:02 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:68711313-59a8-4689-8026-a6a84e8f9e49</guid><dc:creator>Mttrinh</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;As far as I can see this should be possible to do.&lt;/p&gt;
[quote user=""]My application needs to transmit both connectable/scannable and non-connectable_scannble advertisment telegrams continually (no timeout), therefore is not possible to use the &amp;quot;Mesh Advertiser API&amp;quot; correct?[/quote]
&lt;p&gt;Yes, that is correct.&lt;/p&gt;
[quote user=""]It took sometime for me to understand that the nRF Mesh app, does not show devices which only uses ADV bearers. -&amp;gt; please mention that somewhere, like in the App.[/quote]
&lt;p&gt;I will suggest to the developers to add something that mention this in the app.&lt;/p&gt;
&lt;p&gt;You will receive error&lt;span&gt;&amp;nbsp;code 4 (ERROR_NO_MEM)&amp;nbsp;&lt;/span&gt;when you run out of memory, you can try allocate more memory, adjust the RAM size. See if that helps.&lt;/p&gt;
[quote user=""]I assume that the MESH code doers not run/advertise&lt;br /&gt;while it is done in the BLE peripheral part.[/quote]
&lt;p&gt;Your assumption is correct. While the Softdevice is advertising the Mesh won’t be able to advertise. Like it is mentioned in the documentation, the SoftDevice activity will reduce the amount of time the Mesh gets on-air, and in order to maintain a consistently good Mesh performance, the SoftDevice radio parameters must be set as conservatively as possible.&lt;/p&gt;
&lt;p&gt;I also suggest you have a look at the&amp;nbsp;&lt;a href="https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.meshsdk.v4.0.0/md_examples_sdk_coexist_README.html?cp=7_2_3_5" rel="noopener noreferrer" target="_blank"&gt;coexistence examples&lt;/a&gt; if you haven’t already.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: How to add mesh to BLE device</title><link>https://devzone.nordicsemi.com/thread/241047?ContentTypeID=1</link><pubDate>Mon, 23 Mar 2020 09:00:08 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b7194153-acd7-4b5b-be28-7382ef4a9550</guid><dc:creator>BardenDK</dc:creator><description>&lt;p&gt;Here is my complete initialization code, am I missing something. Please let me know if more is needed:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;uint8_t HalBleHandlerStart( uint16_t usCompanyId, uint8_t * pBleMacAddr  )
{
	s_CompanyId = usCompanyId;

	bleperipheral_init( usCompanyId, pBleMacAddr );
	HalMeshHandler_init( scan_mesh_rx_cb );
	HalMeshHandler_start();

	( void ) sd_ble_gap_addr_get( &amp;amp;s_DeviceBleAddr );

	return 1u;
}

/**
 *
 * @param pBleMacAddr
 */
void bleperipheral_init( uint16_t usCompanyId, uint8_t * pBleMacAddr )
{
	s_CompanyId = usCompanyId;

	bleperipheral_stack_init();

	if ( pBleMacAddr != NULL )
	{
		// Set MAC address
		uint32_t err_code;
		ble_gap_addr_t BleAddr;
		BleAddr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC; // Public address type

		for ( uint8_t i = 0; i &amp;lt; BLE_GAP_ADDR_LEN; i++ )
		{
			BleAddr.addr[ i ] = pBleMacAddr[ BLE_GAP_ADDR_LEN - i - 1 ];
		}

		do
		{
			err_code = sd_ble_gap_addr_set( &amp;amp;BleAddr );
		} while ( err_code == NRF_ERROR_BUSY );

		APP_ERROR_CHECK(err_code);
	}

	bleperipheral_gap_params_init();
	bleperipheral_gatt_init();
	advertising_init( 0u );
	bleperipheral_conn_params_init();
	bleperipheral_services_init();
	advertising_start();
}

void bleperipheral_gap_params_init( void )
{
    uint32_t                err_code;
    ble_gap_conn_params_t   gap_conn_params;
    ble_gap_conn_sec_mode_t sec_mode;

    BLE_GAP_CONN_SEC_MODE_SET_OPEN( &amp;amp;sec_mode );

    err_code = sd_ble_gap_device_name_set( &amp;amp;sec_mode,
                                          (const uint8_t *) &amp;quot;&amp;quot;,
                                          0 );
    APP_ERROR_CHECK(err_code);


    memset( &amp;amp;gap_conn_params, 0, sizeof( gap_conn_params ) );

    gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
    gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
    gap_conn_params.slave_latency     = SLAVE_LATENCY;
    gap_conn_params.conn_sup_timeout  = CONN_SUP_TIMEOUT;

    err_code = sd_ble_gap_ppcp_set( &amp;amp;gap_conn_params );
    APP_ERROR_CHECK( err_code );
}

/**@brief Function for initializing the GATT library. */
void bleperipheral_gatt_init( void )
{
    ret_code_t err_code;

    err_code = nrf_ble_gatt_init( &amp;amp;m_bleperipheral_gatt, bleperipheral_gatt_evt_handler );
    APP_ERROR_CHECK(err_code);

    err_code = nrf_ble_gatt_att_mtu_periph_set( &amp;amp;m_bleperipheral_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE );
    APP_ERROR_CHECK(err_code);
}

/**@brief Function for initializing the Advertising functionality.
 */
static void advertising_init( uint8_t bUpdate )
{
	uint32_t               err_code;

    s_gap_adv_data.adv_data.len = BLE_GAP_ADV_SET_DATA_SIZE_MAX;
    s_gap_adv_data.adv_data.p_data = (s_gap_adv_data.adv_data.p_data == s_adv_packet_2 ? s_adv_packet : s_adv_packet_2);
    s_gap_adv_data.scan_rsp_data.len = BLE_GAP_ADV_SET_DATA_SIZE_MAX;
    s_gap_adv_data.scan_rsp_data.p_data = (s_gap_adv_data.scan_rsp_data.p_data == s_scan_rsp_packet_2 ? s_scan_rsp_packet : s_scan_rsp_packet_2);


    ble_gap_adv_params_t advparams;
    ble_advdata_t advdata;
    ble_advdata_t srdata;
    memset( &amp;amp;advdata, 0, sizeof( advdata ) );
    memset( &amp;amp;srdata, 0, sizeof( srdata ) ) ;
    memset( &amp;amp;advparams, 0, sizeof( advparams ) );

    if ( m_conn_handle == BLE_CONN_HANDLE_INVALID )
    {
    	advparams.properties.type 	= BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
    }
    else
    {
    	// In connected state we can&amp;#39;t advertise in connectable mode
    	advparams.properties.type 	= BLE_GAP_ADV_TYPE_NONCONNECTABLE_SCANNABLE_UNDIRECTED;
    }
    advparams.duration			= BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED;
    advparams.filter_policy		= BLE_GAP_ADV_FP_ANY;   /**&amp;lt; Allow scan requests and connect requests from any device. */
    advparams.primary_phy 		= BLE_GAP_PHY_AUTO;
    advparams.secondary_phy		= BLE_GAP_PHY_AUTO;
    advparams.interval			= 320;	// 200 ms adv interval = 320 * 0,625 ms

    advdata.flags 				= BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    advdata.name_type			= BLE_ADVDATA_NO_NAME;
    advdata.include_appearance 	= false;
    advdata.include_ble_device_addr = false;

    // Advertisement will include manufacturer specific data part.
	s_manuf_data_adv.company_identifier = s_CompanyId;
	s_manuf_data_adv.data.p_data = ( uint8_t * ) &amp;amp;s_manuf_data_adv_buf[ 0u ];
	s_manuf_data_adv.data.size = MANUF_DATA_SIZE;
	advdata.p_manuf_specific_data = &amp;amp;s_manuf_data_adv;

	srdata.name_type 			= BLE_ADVDATA_NO_NAME;
	srdata.include_appearance 	= false;
	// Scan response will include manufacturer specific data part.
	s_manuf_data_scanrsp.company_identifier = s_CompanyId;
	s_manuf_data_scanrsp.data.p_data = ( uint8_t * ) &amp;amp;s_manuf_data_scan_rsp_buf[ 0u ];
	s_manuf_data_scanrsp.data.size = MANUF_DATA_SIZE;
	srdata.p_manuf_specific_data = &amp;amp;s_manuf_data_scanrsp;

	err_code = ble_advdata_encode( &amp;amp;srdata, s_gap_adv_data.scan_rsp_data.p_data, &amp;amp;s_gap_adv_data.scan_rsp_data.len );
	APP_ERROR_CHECK(err_code);

	err_code = ble_advdata_encode( &amp;amp;advdata, s_gap_adv_data.adv_data.p_data, &amp;amp;s_gap_adv_data.adv_data.len );
	APP_ERROR_CHECK(err_code);

	if ( bUpdate )
	{
		err_code = sd_ble_gap_adv_set_configure( &amp;amp;m_advertising, &amp;amp;s_gap_adv_data, NULL );
	}
	else
	{
		err_code = sd_ble_gap_adv_set_configure( &amp;amp;m_advertising, &amp;amp;s_gap_adv_data, &amp;amp;advparams );
	}
	APP_ERROR_CHECK(err_code);
}

void bleperipheral_conn_params_init( void )
{
    uint32_t               err_code;
    ble_conn_params_init_t cp_init;

    memset(&amp;amp;cp_init, 0, sizeof(cp_init));

    // NOTE: conn_params already set in gap_params_init()
    cp_init.p_conn_params                  = NULL;
    cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
    cp_init.next_conn_params_update_delay  = NEXT_CONN_PARAMS_UPDATE_DELAY;
    cp_init.max_conn_params_update_count   = MAX_CONN_PARAMS_UPDATE_COUNT;
    cp_init.start_on_notify_cccd_handle    = BLE_GATT_HANDLE_INVALID;
    cp_init.disconnect_on_fail             = false;
    cp_init.evt_handler                    = bleperipheral_on_conn_params_evt;
    cp_init.error_handler                  = bleperipheral_conn_params_error_handler;

    err_code = ble_conn_params_init(&amp;amp;cp_init);
    APP_ERROR_CHECK(err_code);
}

/**@brief Function for initializing services that will be used by the application.
 */
static void bleperipheral_services_init(void)
{
    uint32_t           err_code;
    ble_scomm_init_t     scomm_init;

    // Initialize custom service
    memset(&amp;amp;scomm_init, 0, sizeof(scomm_init));

    scomm_init.data_handler = scomm_data_handler;

    err_code = ble_scomm_init(&amp;amp;m_scomm, &amp;amp;scomm_init);
    APP_ERROR_CHECK(err_code);
}

/**@brief Function for starting advertising.
 */
static void advertising_start(void)
{
    uint32_t err_code = sd_ble_gap_adv_start( m_advertising, APP_BLE_CONN_CFG_TAG );
    APP_ERROR_CHECK(err_code);
}

// public available functions
void HalMeshHandler_init( nrf_mesh_rx_cb_t rx_cb )
{
    mesh_stack_init_params_t init_params =
    {
        .core.irq_priority       				= NRF_MESH_IRQ_PRIORITY_LOWEST,
        .core.lfclksrc           				= DEV_BOARD_LF_CLK_CFG,
        .core.p_uuid             				= NULL,
        .models.models_init_cb   				= models_init_cb,
        .models.config_server_cb 				= config_server_evt_cb,
		.models.health_server_num_selftests 	= 0,
		.models.p_health_server_selftest_array 	= NULL,
		.models.health_server_attention_cb 		= health_server_attention_cb
    };

    uint32_t status = mesh_stack_init( &amp;amp;init_params, &amp;amp;m_device_provisioned );
    switch (status)
    {
        case NRF_ERROR_INVALID_DATA:
            __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, &amp;quot;Data in the persistent memory was corrupted. Device starts as unprovisioned.\n&amp;quot;);
            break;
        case NRF_SUCCESS:
            break;
        default:
            ERROR_CHECK(status);
    }

    if ( rx_cb )
    {
    	s_scan_cb = rx_cb;
    }
    else
    {
    	s_scan_cb = NULL;
    }

    // Enabling ECDH offloading
    ERROR_CHECK( mesh_opt_prov_ecdh_offloading_set( true ) );

    /* Register event handler to receive NRF_MESH_EVT_FLASH_STABLE. Application functionality will
    be started after this event */
    nrf_mesh_evt_handler_add( &amp;amp;m_mesh_core_event_handler );
}

#include &amp;quot;example_common.h&amp;quot;
void HalMeshHandler_start( void )
{
	uint32_t ret = NRF_SUCCESS;
    if ( !m_device_provisioned )
    {
        static const uint8_t static_auth_data[ NRF_MESH_KEY_SIZE ] = STATIC_AUTH_DATA;
        mesh_provisionee_start_params_t prov_start_params =
        {
            .p_static_data    = static_auth_data,
            .prov_complete_cb = provisioning_complete_cb,
            .prov_device_identification_start_cb = NULL,
            .prov_device_identification_stop_cb = NULL,
            .prov_abort_cb = NULL,
			.p_device_uri = EX_URI_LS_CLIENT
        };
        ret = mesh_provisionee_prov_start( &amp;amp;prov_start_params );
        ERROR_CHECK( ret );
    }

    ret = mesh_stack_start();
    ERROR_CHECK( ret );
}&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>