This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

NRF Connect Porting nRF5 SDK application difficulties

I have a functional application that was developed using the nRF5 SDK. I am trying to port this to NRF Connect and I am having difficulties in achieving the same. I am still in the learning stage on NRF Connect.

I set up a scan using my Custom UUID Service. It has two Characteristics, each with its own UUID.
The scan is set for Auto Connect.

In the nrF5 SDK Code when I see the connect I do the following:

case BLE_GAP_EVT_CONNECTED:
          NRF_LOG_INFO("Connected as client.");
          NRF_LOG_FLUSH();
          err_code = ble_bsc_c_handles_assign(&m_ble_bsc_c, p_gap_evt->conn_handle, NULL);
          APP_ERROR_CHECK(err_code);
          err_code = ble_db_discovery_start(&m_db_disc, p_gap_evt->conn_handle);
          

The discovery process then completes and everything works.

I get the folowing event

BLE_BSC_C_EVT_DISCOVERY_COMPLETE:

I have been trying to achieve the same on NRF Connect but I am missing something.
It only seems to work if a Pair is initiated which is not what I require. I do not want to pair.

If I call the following on the connected  event

gatt_discover(conn);

Then I get an error saying that the service was not found.

I can provide more info if required.

Parents
  • Hi,

    It is difficult to say what the issue could be without seeing the related code, all I understand is that you have some issues with your discovery code. Can you show what you have done (with code) and explain how it does not work and how it should work? 

  • Hi - I have reproduced the same issue using your central BAS sample. I inserted one line of code at line 199 to start the discovery process after the connected event. The discovery process fails at line 134.

    What is the correct procedure to follow to make the discovery and handles assigned functions to work properly.

    The way I triggered the connection was to use NRF Connect mobile on my iPhone to initiate the connection using the phone app after setting it up as BAS.

    See the slightly modified sample code below:

    /*
     * Copyright (c) 2019 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    /** @file
     *  @brief Nordic Battery Service Client sample
     */
    
    #include <zephyr/types.h>
    #include <stddef.h>
    #include <inttypes.h>
    #include <errno.h>
    #include <zephyr.h>
    #include <sys/printk.h>
    
    #include <bluetooth/bluetooth.h>
    #include <bluetooth/hci.h>
    #include <bluetooth/conn.h>
    #include <bluetooth/uuid.h>
    #include <bluetooth/gatt.h>
    #include <bluetooth/gatt_dm.h>
    #include <bluetooth/scan.h>
    #include <bluetooth/services/bas_client.h>
    #include <dk_buttons_and_leds.h>
    
    #include <settings/settings.h>
    
    /**
     * Button to read the battery value
     */
    #define KEY_READVAL_MASK DK_BTN1_MSK
    
    #define BAS_READ_VALUE_INTERVAL (10 * MSEC_PER_SEC)
    
    
    static struct bt_conn *default_conn;
    static struct bt_bas_client bas;
    
    static void notify_battery_level_cb(struct bt_bas_client *bas,
    				    uint8_t battery_level);
    
    static void scan_filter_match(struct bt_scan_device_info *device_info,
    			      struct bt_scan_filter_match *filter_match,
    			      bool connectable)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(device_info->recv_info->addr, addr, sizeof(addr));
    
    	printk("Filters matched. Address: %s connectable: %s\n",
    		addr, connectable ? "yes" : "no");
    }
    
    static void scan_connecting_error(struct bt_scan_device_info *device_info)
    {
    	printk("Connecting failed\n");
    }
    
    static void scan_connecting(struct bt_scan_device_info *device_info,
    			    struct bt_conn *conn)
    {
    	default_conn = bt_conn_ref(conn);
    }
    
    static void scan_filter_no_match(struct bt_scan_device_info *device_info,
    				 bool connectable)
    {
    	int err;
    	struct bt_conn *conn;
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	if (device_info->recv_info->adv_type == BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
    		bt_addr_le_to_str(device_info->recv_info->addr, addr,
    				  sizeof(addr));
    		printk("Direct advertising received from %s\n", addr);
    		bt_scan_stop();
    
    		err = bt_conn_le_create(device_info->recv_info->addr,
    					BT_CONN_LE_CREATE_CONN,
    					device_info->conn_param, &conn);
    
    		if (!err) {
    			default_conn = bt_conn_ref(conn);
    			bt_conn_unref(conn);
    		}
    	}
    }
    
    BT_SCAN_CB_INIT(scan_cb, scan_filter_match, scan_filter_no_match,
    		scan_connecting_error, scan_connecting);
    
    static void discovery_completed_cb(struct bt_gatt_dm *dm,
    				   void *context)
    {
    	int err;
    
    	printk("The discovery procedure succeeded\n");
    
    	bt_gatt_dm_data_print(dm);
    
    	err = bt_bas_handles_assign(dm, &bas);
    	if (err) {
    		printk("Could not init BAS client object, error: %d\n", err);
    	}
    
    	if (bt_bas_notify_supported(&bas)) {
    		err = bt_bas_subscribe_battery_level(&bas,
    						     notify_battery_level_cb);
    		if (err) {
    			printk("Cannot subscribe to BAS value notification "
    				"(err: %d)\n", err);
    			/* Continue anyway */
    		}
    	} else {
    		err = bt_bas_start_per_read_battery_level(
    			&bas, BAS_READ_VALUE_INTERVAL, notify_battery_level_cb);
    		if (err) {
    			printk("Could not start periodic read of BAS value\n");
    		}
    	}
    
    	err = bt_gatt_dm_data_release(dm);
    	if (err) {
    		printk("Could not release the discovery data, error "
    		       "code: %d\n", err);
    	}
    }
    
    static void discovery_service_not_found_cb(struct bt_conn *conn,
    					   void *context)
    {
    	printk("The service could not be found during the discovery\n");  ///This gets called after discovery
    }
    
    static void discovery_error_found_cb(struct bt_conn *conn,
    				     int err,
    				     void *context)
    {
    	printk("The discovery procedure failed with %d\n", err);
    }
    
    static struct bt_gatt_dm_cb discovery_cb = {
    	.completed = discovery_completed_cb,
    	.service_not_found = discovery_service_not_found_cb,
    	.error_found = discovery_error_found_cb,
    };
    
    static void gatt_discover(struct bt_conn *conn)
    {
    	int err;
    
    	if (conn != default_conn) {
    		return;
    	}
    
    	err = bt_gatt_dm_start(conn, BT_UUID_BAS, &discovery_cb, NULL);
    	if (err) {
    		printk("Could not start the discovery procedure, error "
    		       "code: %d\n", err);
    	}
    }
    
    static void connected(struct bt_conn *conn, uint8_t conn_err)
    {
    	int err;
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	if (conn_err) {
    		printk("Failed to connect to %s (%u)\n", addr, conn_err);
    		if (conn == default_conn) {
    			bt_conn_unref(default_conn);
    			default_conn = NULL;
    
    			/* This demo doesn't require active scan */
    			err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
    			if (err) {
    				printk("Scanning failed to start (err %d)\n",
    				       err);
    			}
    		}
    
    		return;
    	}
    
    	printk("Connected: %s\n", addr);
    
    
    	err = bt_conn_set_security(conn, BT_SECURITY_L0);
    	if (err) {
    		printk("Failed to set security: %d\n", err);
    
    		gatt_discover(conn);
    	}
    
        gatt_discover(conn);   /// I inserted this here at line 199
    
    }
    
    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));
    
    	printk("Disconnected: %s (reason %u)\n", addr, reason);
    
    	if (default_conn != conn) {
    		return;
    	}
    
    	bt_conn_unref(default_conn);
    	default_conn = NULL;
    
    	/* This demo doesn't require active scan */
    	err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
    	if (err) {
    		printk("Scanning failed to start (err %d)\n", err);
    	}
    }
    
    static void security_changed(struct bt_conn *conn, bt_security_t level,
    			     enum bt_security_err err)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	if (!err) {
    		printk("Security changed: %s level %u\n", addr, level);
    	} else {
    		printk("Security failed: %s level %u err %d\n", addr, level,
    			err);
    	}
    
    	gatt_discover(conn);
    }
    
    static struct bt_conn_cb conn_callbacks = {
    	.connected = connected,
    	.disconnected = disconnected,
    	.security_changed = security_changed
    };
    
    static void scan_init(void)
    {
    	int err;
    
    	struct bt_scan_init_param scan_init = {
    		.connect_if_match = 1,
    		.scan_param = NULL,
    		.conn_param = BT_LE_CONN_PARAM_DEFAULT
    	};
    
    	bt_scan_init(&scan_init);
    	bt_scan_cb_register(&scan_cb);
    
    	err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_UUID, BT_UUID_BAS);
    	if (err) {
    		printk("Scanning filters cannot be set (err %d)\n", err);
    
    		return;
    	}
    
    	err = bt_scan_filter_enable(BT_SCAN_UUID_FILTER, false);
    	if (err) {
    		printk("Filters cannot be turned on (err %d)\n", err);
    	}
    }
    
    static void notify_battery_level_cb(struct bt_bas_client *bas,
    				    uint8_t battery_level)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(bt_bas_conn(bas)),
    			  addr, sizeof(addr));
    	if (battery_level == BT_BAS_VAL_INVALID) {
    		printk("[%s] Battery notification aborted\n", addr);
    	} else {
    		printk("[%s] Battery notification: %"PRIu8"%%\n",
    		       addr, battery_level);
    	}
    }
    
    static void read_battery_level_cb(struct bt_bas_client *bas,
    				  uint8_t battery_level,
    				  int err)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(bt_bas_conn(bas)),
    			  addr, sizeof(addr));
    	if (err) {
    		printk("[%s] Battery read ERROR: %d\n", addr, err);
    		return;
    	}
    
    	printk("[%s] Battery read: %"PRIu8"%%\n", addr, battery_level);
    }
    
    static void button_readval(void)
    {
    	int err;
    
    	printk("Reading BAS value:\n");
    	err = bt_bas_read_battery_level(&bas, read_battery_level_cb);
    	if (err) {
    		printk("BAS read call error: %d\n", err);
    	}
    }
    
    
    static void button_handler(uint32_t button_state, uint32_t has_changed)
    {
    	uint32_t button = button_state & has_changed;
    
    	if (button & KEY_READVAL_MASK) {
    		button_readval();
    	}
    }
    
    
    static void auth_cancel(struct bt_conn *conn)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("Pairing cancelled: %s\n", addr);
    }
    
    
    static void pairing_confirm(struct bt_conn *conn)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	bt_conn_auth_pairing_confirm(conn);
    
    	printk("Pairing confirmed: %s\n", addr);
    }
    
    
    static void pairing_complete(struct bt_conn *conn, bool bonded)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("Pairing completed: %s, bonded: %d\n", addr, bonded);
    }
    
    
    static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("Pairing failed conn: %s, reason %d\n", addr, reason);
    }
    
    
    static struct bt_conn_auth_cb conn_auth_callbacks = {
    	.cancel = auth_cancel,
    	.pairing_confirm = pairing_confirm,
    	.pairing_complete = pairing_complete,
    	.pairing_failed = pairing_failed
    };
    
    
    void main(void)
    {
    	int err;
    
    	printk("Starting Bluetooth Central BAS example\n");
    
    	bt_bas_client_init(&bas);
    
    	err = bt_enable(NULL);
    	if (err) {
    		printk("Bluetooth init failed (err %d)\n", err);
    		return;
    	}
    
    	printk("Bluetooth initialized\n");
    
    	if (IS_ENABLED(CONFIG_SETTINGS)) {
    		settings_load();
    	}
    
    	scan_init();
    	bt_conn_cb_register(&conn_callbacks);
    
    	err = bt_conn_auth_cb_register(&conn_auth_callbacks);
    	if (err) {
    		printk("Failed to register authorization callbacks.\n");
    		return;
    	}
    
    	err = dk_buttons_init(button_handler);
    	if (err) {
    		printk("Failed to initialize buttons (err %d)\n", err);
    		return;
    	}
    
    	err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
    	if (err) {
    		printk("Scanning failed to start (err %d)\n", err);
    		return;
    	}
    
    	printk("Scanning successfully started\n");
    }
    

  • I am not sure how you configured this on you phone, but when I test with the Bluetooth: Central BAS and the Bluetooth: Peripheral HIDS keyboard as the peripheral (both from NCS 1.5.1) this works as it should, also with your modifications. This is in line with my expectation. So I suspect you have an issue with the configuration on the peripheral side which you use to test with. Please try with the HIDS keyboard sample.

  • I did what you said and it did work. Trying a new direction. Will let you know.

Reply Children
No Data
Related