bt_nus_send Failed

I tried to establish communication between the two development boards and the phone. The specific process is as follows: One development board works in slave mode and the other board works in master mode to receive data sent from the slave and forward the received data to the cell phone.

The code for forwarding is as follows:

static uint8_t ble_data_received(struct bt_nus_client *nus,struct bt_conn *conn,
						const uint8_t *data, uint16_t len)
{


	if (bt_nus_send(conn,  data, len)) {
		LOG_WRN("Failed to send data over BLE connection");
	}

	return BT_GATT_ITER_CONTINUE;
}

But the serial debugger will show "Failed to send data over BLE_connection".

Another problem: I'm not quite sure where the "conn" is being assigned. Since this board works as both a slave and a master, I need to know which device the "conn" represents.

Parents
  • Hello,

    So you have one DK acting as a peripheral, and you connect it to two mobile phones acting as centrals, is that the case?

    You figured out that bt_nus_send() returns something other than 0, since you are checking the value. But can you please check what it returns?

    int err;
    
    err = bt_nus_send(conn, data, len);
    
    if (err) {
        LOG_WRN("bt_nus_send() returned %d", err);
    }
    return err;

    Best regards,

    Edvin

  • So you have one DK acting as a peripheral, and you connect it to two mobile phones acting as centrals, is that the case?

    What I mean is that I have two DKs, one only as a slave to the other, and one both as a master to the previous DK and as a slave to the phone.

    But can you please check what it returns?

    I will try it later.

    But what I want to know most is where "conn" is assigned, or which device it represents when a DK is connected to two devices.

  • I was wondering if “data” is empty, does that cause “bt_nus_send()” to fail?

  • Hello,

    If bt_nus_send() returns -22, it means EINVAL.

    It probably means that your conn pointer is invalid. Please note how the peripheral_uart sample stores the current_conn pointer in the connected event (and that it invalidates it in the disconnected event). That current_conn parameter is one that you could enter into bt_nus_send().

    Since you want to have two connections, you can check your role in the connected event:

    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	if (err) {
    		LOG_ERR("Connection failed (err %u)", err);
    		return;
    	}
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    	LOG_INF("Connected %s", addr);
    
    	current_conn = bt_conn_ref(conn);
    
    	dk_set_led_on(CON_STATUS_LED);
    	
    	if (conn->role == BT_CONN_ROLE_CENTRAL)
    	{
    	    LOG_INF("I am the central in this connection.");
    	}
    	else if (conn_role == BT_CONN_ROLE_PERIPHERAL)
    	{
    	    LOG_INF("I am the peripheral in this connection.");
    	}
    }

    Best regards,

    Edvin

  • When I try to use "conn->role", ”Pointer to incomplete class type not allow“ was reported

    if (conn->role == BT_CONN_ROLE_CENTRAL)
    	{
    	    LOG_INF("I am the central in this connection.");
    	}
    else if (conn->role == BT_CONN_ROLE_PERIPHERAL)
    	{
    	    LOG_INF("I am the peripheral in this connection.");
    	}

    And in my project, the connected and disconnected event are as follow.

    static void connected(struct bt_conn *conn, uint8_t conn_err)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    	int8_t txp;
    	int err;
    	int ret;
    	struct bt_conn_info info;
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	if (conn_err) {
    		LOG_INF("Failed to connect to %s (%d)", log_strdup(addr),
    			conn_err);
    
    		if (default_conn == conn) {
    			bt_conn_unref(default_conn);
    			default_conn = NULL;
    
    			err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
    			if (err) {
    				LOG_ERR("Scanning failed to start (err %d)",
    					err);
    			}
    		}
    
    		return;
    	}
    	else{
    		default_conn = bt_conn_ref(conn);
    		ret = bt_hci_get_conn_handle(default_conn,
    					     &default_conn_handle);
    		if (ret) {
    			printk("No connection handle (err %d)\n", ret);
    		} else {
    			/* Send first at the default selected power */
    			bt_addr_le_to_str(bt_conn_get_dst(conn),
    							  addr, sizeof(addr));
    			printk("Connected via connection (%d) at %s\n",
    			       default_conn_handle, addr);
    
    			set_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_CONN,
    				     default_conn_handle,
    				     tx_power);
    
    			get_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_CONN,
    				     default_conn_handle, &txp);
    			printk("Connection (%d) - Tx Power = %d\n",
    			       default_conn_handle, txp);
    		}
    	}
    
    	LOG_INF("Connected: %s", log_strdup(addr));
    	LOG_INF("Connection- Tx Power = %d", txp);
    
    	static struct bt_gatt_exchange_params exchange_params;
    
    	exchange_params.func = exchange_func;
    	err = bt_gatt_exchange_mtu(conn, &exchange_params);
    	if (err) {
    		LOG_WRN("MTU exchange failed (err %d)", err);
    	}
    
    	err = bt_conn_set_security(conn, BT_SECURITY_L2);
    	if (err) {
    		LOG_WRN("Failed to set security: %d", err);
    
    		gatt_discover(conn);
    	}
    
    	err = bt_scan_stop();
    	if ((!err) && (err != -EALREADY)) {
    		LOG_ERR("Stop LE scan failed (err %d)", err);
    	}
    	bt_conn_get_info(conn, &info);
    
    	if (info.role == BT_CONN_ROLE_CENTRAL) {
    		dk_set_led_on(CON_STATUS_LED);
    
    		err = bt_conn_set_security(conn, BT_SECURITY_L2);
    		if (err) {
    			printk("Failed to set security (err %d)\n", err);
    
    			gatt_discover(conn);
    		}
    	} else {
    		dk_set_led_on(PERIPHERAL_CONN_STATUS_LED);
    	}
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    	int err;
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	LOG_INF("Disconnected: %s (reason %u)", log_strdup(addr),
    		reason);
    
    	if (default_conn != conn) {
    		dk_set_led_off(PERIPHERAL_CONN_STATUS_LED);
    		return;
    	}
    
    	bt_conn_unref(default_conn);
    	default_conn = NULL;
    
    	err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
    	if (err) {
    		LOG_ERR("Scanning failed to start (err %d)",
    			err);
    	}
    	
    	// dk_set_led_off(CON_STATUS_LED);
    }

    "default_conn" should be equal to "current_conn" that can be entered into bt_nus_send(). But in this case, my phone can't connect to that DK when it's already connected to another DK. In addition, bt_nus_send failed either. 

    That current_conn parameter is one that you could enter into bt_nus_send().

    So I was wondering, do I need two variables to represent the two different devices the DK connected to?

    Looking for your answer!

  • ell_pass said:

    So I was wondering, do I need two variables to represent the two different devices the DK connected to?

    Yes, you do. Aslo note that as a central, the API is different than from the peripheral. if you are a peripheral (connected to a central), you should use bt_nus_send(), as it does in the peripheral_uart sample. If you are the central in the connection (and you are connected to a peripheral), you should use the API bt_nus_client_send(), as it is used in the central_uart sample.

    And again, yes, you need two different conn handles. One for the central and one for the peripheral. 

    Best regards,

    Edvin

  • Hello,

    Thanks for your help!It works well.

    Best regards,

    ell_pass

Reply Children
No Data
Related