multi-nus peripheral nrf52833

Hi All!

Hope you are doing well! I am using the multi-NUS-master.zip, https://github.com/NordicMatt/multi-NUS.

Converted the above-mentioned code to NCS version 2.0.2 and for peripheral_uart I am using 2.3.0 using Vscode studio as an IDE.

I set one device as Central(nrf52833DK) and loaded the above-mentioned code with some changes to work it for coded phy.

and 2 more devices (nrf52833DK and custom (nrf52833)) loaded with peripheral_uart code (coded phy). 

Everything works fine. Both the peripherals connect and disconnect with bidirectional data transfer.

Now the issue I am facing is that,

1) Sometimes 2 out of 10 times, when I reset both the peripherals to connect again with the central, the central device not scanning the peripherals 

Although both are advertising as I reset both.

2)To solve the above point, when I reset the central then it connects both the peripherals again and starts communication. Central is not in a hang state because hello messages are seen at the dock light.

3)Sometimes 3 out of 10 times, the custom board (nrf52833) stops communication with the central automatically so need to reset it. But it never happened with peripheral (DK).

4)Is there any filter on the Mac address? .Because the Custom board address starts with F7:13 and DK from E2:2B.malfuncationing behaviour observed with central as mentioned in point #  3 

I have attached the central converted code to ncs 2.0.2 

/*
 * Copyright (c) 2018 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
 */

/** @file
 *  @brief Nordic UART Service Client sample
 */

#include <errno.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/printk.h>

#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/bluetooth/gatt.h>

#include <bluetooth/services/nus.h>
#include <bluetooth/services/nus_client.h>
#include <bluetooth/gatt_dm.h>
#include <bluetooth/scan.h>
#include <bluetooth/conn_ctx.h>

#include <zephyr/settings/settings.h>

#include <zephyr/drivers/uart.h>

#include <zephyr/logging/log.h>

//#include <bluetooth/conn.h>

#define LOG_MODULE_NAME central_uart
LOG_MODULE_REGISTER(LOG_MODULE_NAME,LOG_LEVEL_DBG);

/* UART payload buffer element size. */
#define UART_BUF_SIZE 20   // 20

#define KEY_PASSKEY_ACCEPT DK_BTN1_MSK
#define KEY_PASSKEY_REJECT DK_BTN2_MSK

#define NUS_WRITE_TIMEOUT K_MSEC(150)
#define UART_WAIT_FOR_BUF_DELAY K_MSEC(50)
#define UART_RX_TIMEOUT 50

#define ROUTED_MESSAGE_CHAR '*'
#define BROADCAST_INDEX 99

static const struct device *uart = DEVICE_DT_GET(DT_NODELABEL(uart0));
static struct k_work_delayable uart_work;

static K_SEM_DEFINE(nus_write_sem, 0, 1);

struct uart_data_t {
	void *fifo_reserved;
	uint8_t  data[UART_BUF_SIZE];
	uint16_t len;
};


BT_CONN_CTX_DEF(conns, CONFIG_BT_MAX_CONN, sizeof(struct bt_nus_client));

static K_FIFO_DEFINE(fifo_uart_tx_data);
static K_FIFO_DEFINE(fifo_uart_rx_data);

static struct bt_conn *default_conn;

static bool routedMessage = false;
static bool messageStart = true;

static struct bt_nus_client nus_client;

struct bt_le_scan_param m_scan_param = {
		.type     = BT_LE_SCAN_TYPE_ACTIVE,
		.interval = BT_GAP_SCAN_FAST_INTERVAL,
		.window   = BT_GAP_SCAN_FAST_WINDOW,
		.options  = BT_LE_SCAN_OPT_CODED | BT_LE_SCAN_OPT_NO_1M
	};
/*
static void ble_data_sent(struct bt_nus_client *nus, uint8_t err,
					const uint8_t *const data, uint16_t len)
{
	ARG_UNUSED(nus);

	struct uart_data_t *buf;

	// Retrieve buffer context. //
	buf = CONTAINER_OF(data, struct uart_data_t, data);
	k_free(buf);

	k_sem_give(&nus_write_sem);

	if (err) {
		LOG_WRN("ATT error code: 0x%02X", err);
	}
}
*/
static void ble_data_sent(uint8_t err, const uint8_t *const data, uint16_t len)
{

	k_sem_give(&nus_write_sem);

	if (err) {
		LOG_WRN("ATT error code: 0x%02X", err);
	}
}

/*	New function for sending data into the multi-NUS
* 	Extensions to the behavior of message routing can be made here.
*	If the first character is *, this indicates a routed message.
*	If the first character is not *, then this is a broadcast message sent to all peers.
* 	Iaf the message is routed, the two characters after the * will be read as the peer number
*	and the message will be sent only to that peer. Numbers must be written as two digits, i.e 01 for 1.
*	The default behavior will be to broadcast in the case of failure of message parsing.
*/
static int multi_nus_send(struct uart_data_t *buf){
	
	int err = 0;
	char * message = buf->data;
	int length = buf->len;
	
	static bool broadcast = false;
	static int nus_index = 0;

	LOG_INF("Multi-Nus Send");

	/*How many connections are there in the Connection Context Library?*/
	const size_t num_nus_conns = bt_conn_ctx_count(&conns_ctx_lib);

	/*Handle the routing of the message only at the beginning of the message*/
	if (messageStart) {
		messageStart = false;

		/*Check if it's a routed message*/
		if (message[0] == ROUTED_MESSAGE_CHAR) {
			
			routedMessage = true;
			/*Determine who the intended recipient is*/
			char str[2];
			str[0] = message[1];
			str[1] = message[2];
			nus_index = atoi(str);

			/*Is this a number that makes sense?*/
			if ((nus_index >= 0) && (nus_index < num_nus_conns)){
				broadcast = false;

				/*Move the data buffer pointer to after the recipient info and 
				shorten the length*/
				message =  &message[3];
				length = length - 3;
			} else if (nus_index == BROADCAST_INDEX) {
				broadcast = true;
				message =  &message[3];
				length = length - 3;
			}
		} else {
			broadcast = true;
		}
	}


	/*	If it's a routed message, send it to that guy. 
	*	If it's not, broadcast it to everyone.
	*/
	if (broadcast == false){
		const struct bt_conn_ctx *ctx =
				bt_conn_ctx_get_by_id(&conns_ctx_lib, nus_index);
		
		LOG_INF("Trying to send to server %d", nus_index);

		if (ctx) {
			struct bt_nus_client *nus_client = ctx->data;

			if (nus_client) {
				err = bt_nus_client_send(nus_client,
								     message,
								     length);
				if (err) {
					LOG_WRN("Failed to send data over BLE connection"
						"(err %d)",
						err);
				}else{
					LOG_INF("Sent to server %d: %s", nus_index, log_strdup(message));
				}
			
				

				err = k_sem_take(&nus_write_sem,
							NUS_WRITE_TIMEOUT);
				if (err) {
					LOG_WRN("NUS send timeout");
				}
			}

			bt_conn_ctx_release(&conns_ctx_lib,
							(void *)ctx->data);
		}

	}else{//Broadcast message
		LOG_INF("Broadcast");
		for (int i = 0; i < num_nus_conns; i++) {
			const struct bt_conn_ctx *ctx =
				bt_conn_ctx_get_by_id(&conns_ctx_lib, i);
		
			if (ctx) {
				struct bt_nus_client *nus_client = ctx->data;
				
				if (nus_client) {
					err = bt_nus_client_send(nus_client,
								     message,
								     length);
					if (err) {
						LOG_WRN("Failed to send data over BLE connection"
							"(err %d)",
							err);
					}else{
						LOG_INF("Sent to server %d: %s", i, log_strdup(message));
					}

					bt_conn_ctx_release(&conns_ctx_lib,
							    (void *)ctx->data);

					err = k_sem_take(&nus_write_sem,
							 NUS_WRITE_TIMEOUT);
					if (err) {
						LOG_WRN("NUS send timeout");
					}
				}
			}
		}
	}

	if ( (message[length-1] == '\n') || (message[length-1] == '\r') ) {
		messageStart = true;
		routedMessage = false;
	}

	return err;
}

/*	This function has been updated to add the ability for a peer to route a message by
*	appending a '*' as in the multi-NUS send function. So a peer could send the message
*	*00 to send a message to peer 0. If the peer sends a *99, that message is broadcast to 
*	all peers
*/

static uint8_t ble_data_received(struct bt_nus_client *nus,
						const uint8_t *data, uint16_t len)
{
	ARG_UNUSED(nus);

	int err;

	for (uint16_t pos = 0; pos != len;) {
		struct uart_data_t *tx = k_malloc(sizeof(*tx));

		if (!tx) {
			LOG_WRN("Not able to allocate UART send data buffer");
			return BT_GATT_ITER_CONTINUE;
		}

		/* Keep the last byte of TX buffer for potential LF char. */
		size_t tx_data_size = sizeof(tx->data) ;//- 1; Added 

		if ((len - pos) > tx_data_size) {
			tx->len = tx_data_size;
		} else {
			tx->len = (len - pos);
		}

		memcpy(tx->data, &data[pos], tx->len);

		pos += tx->len;

		/* Append the LF character when the CR character triggered
		 * transmission from the peer.
		 */
		if ((pos == len) && (data[len - 1] == '\r')) {
			tx->data[tx->len] = '\n';
			tx->len++;
		}

        /*	Routed messages. See the comments above. 
		*	Check for *, if there's a star, send it over to the multi-nus send function
		*/

	    if (( data[0] == '*') || (routedMessage == true) ) {
			multi_nus_send(tx);
		}


		err = uart_tx(uart, tx->data, tx->len, SYS_FOREVER_MS);
		if (err) {
			k_fifo_put(&fifo_uart_tx_data, tx);
		}
	}

	return BT_GATT_ITER_CONTINUE;
}

static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
{
	ARG_UNUSED(dev);

	static size_t aborted_len;
	struct uart_data_t *buf;
	static uint8_t *aborted_buf;
	static bool disable_req;

	switch (evt->type) {
	case UART_TX_DONE:
		LOG_DBG("UART_TX_DONE");
		if ((evt->data.tx.len == 0) ||
		    (!evt->data.tx.buf)) {
			return;
		}

		if (aborted_buf) {
			buf = CONTAINER_OF(aborted_buf, struct uart_data_t,
					   data);
			aborted_buf = NULL;
			aborted_len = 0;
		} else {
			buf = CONTAINER_OF(evt->data.tx.buf,
					   struct uart_data_t,
					   data);
		}

		k_free(buf);

		buf = k_fifo_get(&fifo_uart_tx_data, K_NO_WAIT);
		if (!buf) {
			return;
		}

		if (uart_tx(uart, buf->data, buf->len, SYS_FOREVER_MS)) {
			LOG_WRN("Failed to send data over UART");
		}

		break;

	case UART_RX_RDY:
		LOG_DBG("UART_RX_RDY");
		buf = CONTAINER_OF(evt->data.rx.buf, struct uart_data_t, data);
		buf->len += evt->data.rx.len;

		if (disable_req) {
			return;
		}

		if ((evt->data.rx.buf[buf->len - 1] == '\n') ||
		    (evt->data.rx.buf[buf->len - 1] == '\r')) {
			disable_req = true;
			uart_rx_disable(uart);
		}

		break;

	case UART_RX_DISABLED:
		LOG_DBG("UART_RX_DISABLED");
		disable_req = false;

		buf = k_malloc(sizeof(*buf));
		if (buf) {
			buf->len = 0;
		} else {
			LOG_WRN("Not able to allocate UART receive buffer");
			k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
			return;
		}

		uart_rx_enable(uart, buf->data, sizeof(buf->data),
			       UART_RX_TIMEOUT);


       
		break;

	case UART_RX_BUF_REQUEST:
		LOG_DBG("UART_RX_BUF_REQUEST");
		buf = k_malloc(sizeof(*buf));
		if (buf) {
			buf->len = 0;
			uart_rx_buf_rsp(uart, buf->data, sizeof(buf->data));
		} else {
			LOG_WRN("Not able to allocate UART receive buffer");
		}

		break;

	case UART_RX_BUF_RELEASED:
		LOG_DBG("UART_RX_BUF_RELEASED");
		buf = CONTAINER_OF(evt->data.rx_buf.buf, struct uart_data_t,
				   data);

		if (buf->len > 0) {
			k_fifo_put(&fifo_uart_rx_data, buf);
		} else {
			k_free(buf);
		}

		break;

	case UART_TX_ABORTED:
		LOG_DBG("UART_TX_ABORTED");
		if (!aborted_buf) {
			aborted_buf = (uint8_t *)evt->data.tx.buf;
		}

		aborted_len += evt->data.tx.len;
		buf = CONTAINER_OF(aborted_buf, struct uart_data_t,
				   data);

		uart_tx(uart, &buf->data[aborted_len],
			buf->len - aborted_len, SYS_FOREVER_MS);

		break;

	default:
		break;
	}
}

static void uart_work_handler(struct k_work *item)
{
	struct uart_data_t *buf;

	buf = k_malloc(sizeof(*buf));
	if (buf) {
		buf->len = 0;
	} else {
		LOG_WRN("Not able to allocate UART receive buffer");
		k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
		return;
	}

	uart_rx_enable(uart, buf->data, sizeof(buf->data), UART_RX_TIMEOUT);
}

static int uart_init(void)
{
	int err;
	struct uart_data_t *rx;

	if (!device_is_ready(uart)) {
		LOG_ERR("UART device not ready");
		return -ENODEV;
	}

	rx = k_malloc(sizeof(*rx));
	if (rx) {
		rx->len = 0;
	} else {
		return -ENOMEM;
	}

	k_work_init_delayable(&uart_work, uart_work_handler);

	err = uart_callback_set(uart, uart_cb, NULL);
	if (err) {
		return err;
	}

	return uart_rx_enable(uart, rx->data, sizeof(rx->data),
			      UART_RX_TIMEOUT);
}

static void discovery_complete(struct bt_gatt_dm *dm,
			       void *context)
{
	struct bt_nus_client *nus = context;
	LOG_INF("Service discovery completed");

	bt_gatt_dm_data_print(dm);

	bt_nus_handles_assign(dm, nus);
	bt_nus_subscribe_receive(nus);

	bt_gatt_dm_data_release(dm);

    // Added code from multinus

	int err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
	if (err) {
		LOG_ERR("Scanning failed to start (err %d)", err);
	} else {
		LOG_INF("Scanning started");
	}

	/*	Send a message to the new NUS server informing it of its ID in this 
	*	mini-network
	*	The new NUS will have been added to the connection context library and so
	* 	will be the highest index as they are added incrementally upwards.
	*	This is a bit of a workaround because in this function, I don't know
	*	the ID of this connection which is the piece of info I want to transmit.
	*/
	size_t num_nus_conns = bt_conn_ctx_count(&conns_ctx_lib);
	size_t nus_index = 99;

	/*	This is a little inelegant but we must get the index of the device to
	* 	convey it. This bit sends the index number to the peripheral.
	*/
	for (size_t i = 0; i < num_nus_conns; i++) {
		const struct bt_conn_ctx *ctx =
			bt_conn_ctx_get_by_id(&conns_ctx_lib, i);

		if (ctx) {
			if (ctx->data == nus) {
				nus_index = i;
				char message[3];
				sprintf(message, "%d", nus_index);
				message[2] = '\r';
				int length = 3;

				err = bt_nus_client_send(nus, message, length);
				if (err) {
					LOG_WRN("Failed to send data over BLE connection"
						"(err %d)",
						err);
				} else {
					LOG_INF("Sent to server %d: %s",
						nus_index, log_strdup(message));
				}

				bt_conn_ctx_release(&conns_ctx_lib,
						    (void *)ctx->data);
				break;
			} else {
				bt_conn_ctx_release(&conns_ctx_lib,
						    (void *)ctx->data);
			}
		}
	}


}

static void discovery_service_not_found(struct bt_conn *conn,
					void *context)
{
	LOG_INF("Service not found");
}

static void discovery_error(struct bt_conn *conn,
			    int err,
			    void *context)
{
	LOG_WRN("Error while discovering GATT database: (%d)", err);
}

struct bt_gatt_dm_cb discovery_cb = {
	.completed         = discovery_complete,
	.service_not_found = discovery_service_not_found,
	.error_found       = discovery_error,
};
/*
static void gatt_discover(struct bt_conn *conn)
{
	int err;

	if (conn != default_conn) {
		return;
	}

	err = bt_gatt_dm_start(conn,
			       BT_UUID_NUS_SERVICE,
			       &discovery_cb,
			       &nus_client);
	if (err) {
		LOG_ERR("could not start the discovery procedure, error "
			"code: %d", err);
	}
}

*/
static void gatt_discover(struct bt_conn *conn)
{
	int err;

	struct bt_nus_client *nus_client =
		bt_conn_ctx_get(&conns_ctx_lib, conn);

	if (!nus_client) {
		return;
	}

	err = bt_gatt_dm_start(conn,
			       BT_UUID_NUS_SERVICE,
			       &discovery_cb,
			       nus_client);
	if (err) {
		LOG_ERR("could not start the discovery procedure, error "
			"code: %d", err);
	}

	bt_conn_ctx_release(&conns_ctx_lib, (void *) nus_client);

}
static void exchange_func(struct bt_conn *conn, uint8_t err, struct bt_gatt_exchange_params *params)
{
	if (!err) {
		LOG_INF("MTU exchange done");
	} else {
		LOG_WRN("MTU exchange failed (err %" PRIu8 ")", err);
	}
}

static void connected(struct bt_conn *conn, uint8_t conn_err)
{
	char addr[BT_ADDR_LE_STR_LEN];
	int err;

    struct bt_nus_client_init_param init = {   // code added 
		.cb = {
			.received = ble_data_received,
			.sent = ble_data_sent,
		}
	};

	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);

			printk("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);
					printk("Scanning failed to start (err %d)",
					err);
			}
		}

		return;
	}

	LOG_INF("Connected: %s", log_strdup(addr));

	// code added 
   
	/*Allocate memory for this connection using the connection context library. For reference,
	this code was taken from hids.c
	*/
	struct bt_nus_client *nus_client = bt_conn_ctx_alloc(&conns_ctx_lib, conn);

	if (!nus_client) {
		LOG_WRN("There is no free memory to "
			"allocate the connection context");
	}

	memset(nus_client, 0, bt_conn_ctx_block_size_get(&conns_ctx_lib));

	err = bt_nus_client_init(nus_client, &init);

	bt_conn_ctx_release(&conns_ctx_lib, (void *)nus_client);
	
	if (err) {
		LOG_ERR("NUS Client initialization failed (err %d)", err);
	}else{
		LOG_INF("NUS Client module initialized");
	}

	gatt_discover(conn);

   /*
	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);
	}
}

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);

    err = bt_conn_ctx_free(&conns_ctx_lib, conn);  // code added	

	if (err) {
		LOG_WRN("The memory was not allocated for the context of this "
			"connection.");
	}

	bt_conn_unref(conn);
	default_conn = NULL;
	
	/*

	if (default_conn != conn) {
		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);
	}

	*/
}

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) {
		LOG_INF("Security changed: %s level %u", log_strdup(addr),
			level);
	} else {
		LOG_WRN("Security failed: %s level %u err %d", log_strdup(addr),
			level, err);
	}

	gatt_discover(conn);
}

BT_CONN_CB_DEFINE(conn_callbacks) = {
	.connected = connected,
	.disconnected = disconnected,
	.security_changed = security_changed
};

static void scan_filter_match(struct bt_scan_device_info *device_info,
			      struct bt_scan_filter_match *filter_match,
			      bool connectable)
{

	int err;

    char addr[BT_ADDR_LE_STR_LEN];

	struct bt_conn_le_create_param *conn_params;
	 

	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");

	err = bt_scan_stop();
	if (err) {
		printk("Stop LE scan failed (err %d)\n", err);
	}

	conn_params = BT_CONN_LE_CREATE_PARAM(
			BT_CONN_LE_OPT_CODED | BT_CONN_LE_OPT_NO_1M,
			BT_GAP_SCAN_FAST_INTERVAL,
			BT_GAP_SCAN_FAST_INTERVAL);

	err = bt_conn_le_create(device_info->recv_info->addr, conn_params,
				BT_LE_CONN_PARAM_DEFAULT,
				&default_conn);

	if (err) {
		printk("Create conn failed (err %d)\n", err);

		err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
		if (err) {
			printk("Scanning failed to start (err %d)\n", err);
			return;
		}
	}

	printk("Connection pending\n");
}

//BT_SCAN_CB_INIT(scan_cb, scan_filter_match, NULL, NULL, NULL);
//BT_SCAN_CB_INIT(scan_cb, scan_filter_match, NULL,scan_connecting_error, scan_connecting);

static void scan_connecting_error(struct bt_scan_device_info *device_info)
{
	LOG_WRN("Connecting failed");
}

static void scan_connecting(struct bt_scan_device_info *device_info,
			    struct bt_conn *conn)
{
	default_conn = bt_conn_ref(conn);
}

static int nus_client_init(void)
{
	int err;
	struct bt_nus_client_init_param init = {
		.cb = {
			.received = ble_data_received,
			.sent = ble_data_sent,
		}
	};

	err = bt_nus_client_init(&nus_client, &init);
	if (err) {
		LOG_ERR("NUS Client initialization failed (err %d)", err);
		return err;
	}

	LOG_INF("NUS Client module initialized");
	return err;
}

BT_SCAN_CB_INIT(scan_cb, scan_filter_match, NULL,scan_connecting_error, scan_connecting);


static void scan_init(void)
{
	int err;

	// Use active scanning and disable duplicate filtering to handle any
	 // devices that might update their advertising data at runtime. 
	
    const char *perName1="Nordic_UART_Service";

    struct bt_le_conn_param m_conn_param={
        .interval_min=120,
		.interval_max=220,
		.timeout=100,

	}; 
	struct bt_scan_init_param scan_init = {
		.connect_if_match = 1,            //1
		.scan_param = &m_scan_param,
		.conn_param = &m_conn_param,     //NULL              // 

	};

	bt_scan_init(&scan_init);
	bt_scan_cb_register(&scan_cb);

	//err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_UUID, BT_UUID_NUS_SERVICE);
     err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_NAME,perName1);

	if (err) {
		printk("Scanning filters cannot be set (err %d)\n", err);

		return;
	}

	//err = bt_scan_filter_enable(BT_SCAN_UUID_FILTER, false);
    err = bt_scan_filter_enable(BT_SCAN_NAME_FILTER, false);
	if (err) {
		printk("Filters cannot be turned on (err %d)\n", err);
	}
}

/*
static int scan_init(void)
{
	int err;
	struct bt_scan_init_param scan_init = {
		.connect_if_match = 1,
	};

	bt_scan_init(&scan_init);
	bt_scan_cb_register(&scan_cb);

	err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_UUID, BT_UUID_NUS_SERVICE);
	if (err) {
		LOG_ERR("Scanning filters cannot be set (err %d)", err);
		return err;
	}

	err = bt_scan_filter_enable(BT_SCAN_UUID_FILTER, false);
	if (err) {
		LOG_ERR("Filters cannot be turned on (err %d)", err);
		return err;
	}

	LOG_INF("Scan module initialized");
	return err;
}

*/

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));

	LOG_INF("Pairing cancelled: %s", log_strdup(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));

	LOG_INF("Pairing completed: %s, bonded: %d", log_strdup(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));

	LOG_WRN("Pairing failed conn: %s, reason %d", log_strdup(addr),
		reason);
}

static struct bt_conn_auth_cb conn_auth_callbacks = {
	.cancel = auth_cancel,
};

static struct bt_conn_auth_info_cb conn_auth_info_callbacks = {
	
	.pairing_complete = pairing_complete,
	.pairing_failed = pairing_failed
};

void main(void)
{
	int err;

	err = bt_conn_auth_cb_register(&conn_auth_callbacks);
	if (err) {
		LOG_ERR("Failed to register authorization callbacks.");
		return;
	}
/*
	err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks);
	if (err) {
		printk("Failed to register authorization info callbacks.\n");
		return;
	}

*/
	err = bt_enable(NULL);
	if (err) {
		LOG_ERR("Bluetooth init failed (err %d)", err);
		return;
	}
	LOG_INF("Bluetooth initialized");

	if (IS_ENABLED(CONFIG_SETTINGS)) {
		settings_load();
	}

  //  bt_conn_cb_register(&conn_callback);

	int (*module_init[])(void) = {uart_init, scan_init, nus_client_init};
	for (size_t i = 0; i < ARRAY_SIZE(module_init); i++) {
		err = (*module_init[i])();
		if (err) {
			return;
		}
	}

	printk("Starting Bluetooth Central UART example\n");


	err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
	if (err) {
		LOG_ERR("Scanning failed to start (err %d)", err);
		return;
	}
   
	LOG_INF("Scanning successfully started");

	for (;;) {
		// Wait indefinitely for data to be sent over Bluetooth //
		/*struct uart_data_t *buf = k_fifo_get(&fifo_uart_rx_data,
						     K_FOREVER);

		err = bt_nus_client_send(&nus_client, buf->data, buf->len);
		if (err) {
			LOG_WRN("Failed to send data over BLE connection"
				"(err %d)", err);

				printk("Failed to send data over BLE connection"
        "(err %d)", err);
		}

		err = k_sem_take(&nus_write_sem, NUS_WRITE_TIMEOUT);
		if (err) {
			LOG_WRN("NUS send timeout");
			printk("NUS send timeout");
		} */


			/* Wait indefinitely for data to be sent over Bluetooth */
		struct uart_data_t *buf = k_fifo_get(&fifo_uart_rx_data,
						     K_FOREVER);
		multi_nus_send(buf);	

		k_free(buf);
	} 
}

Thanks and Regards,

Muhammad Usman

Parents
  • Hello,

    We are trying to even out the workload after the summer holidays, so Simon asked if I could take a look at this ticket.

    Can you please upload both the central and peripheral applications that you are using?

    When you reset both the peripheral devices, and they are not reconnected (2 out of 10 times), do you see the disconnected event in the central device? (It looks like it should print it in the log).

    3)Sometimes 3 out of 10 times, the custom board (nrf52833) stops communication with the central automatically so need to reset it. But it never happened with peripheral (DK).

    When this happens, do you see a disconnected event either in the central or the peripheral? You say that they stop communicating. What usually triggers the communication? Is it a timer that times out? is it a button press? Is it a UART command? Are you using bt_nus_send() to communicate? Is that still being called? What does it return?

    4)Is there any filter on the Mac address? .Because the Custom board address starts with F7:13 and DK from E2:2B.malfuncationing behaviour observed with central as mentioned in point #  3 

    What do you mean by filtering on Mac address? During scanning/connection, or while being connected?

    It is possible to filter on Mac addresses, but it is not really that common, because it would require a designated application for all devices (in mass production). Usually you would filter on advertising data (advertised UUID or an advertising name). When you are connected to multiple devices, you can use the conn pointers from the connected event. I would recommend storing these as long as the connection remains. This means setting it in the connected event, and setting it to NULL in the disconnected event. You can store an array of static struct bt_conn*, much like the central_uart from the ncs\nrf\samples\bluetooth\central_uart does (although it doesn't store it as an array, as it only handles one connection). Look at how this sample does that, and try to implement something similar.

    Best regards,

    Edvin

  • Hi Edvin,

    Thank you for the response! 

    Can you please upload both the central and peripheral applications that you are using?

    Peripherals Side FWH: ncs v2.3.0

    Multicon_inter_Reg_peri-main_Luis_V1.zip

    Central side FWH: ncs v2.0.2

    central_uart_con_202.zip

    When this happens, do you see a disconnected event either in the central or the peripheral? You say that they stop communicating. What usually triggers the communication? Is it a timer that times out? is it a button press? Is it a UART command? Are you using bt_nus_send() to communicate? Is that still being called? What does it return?

     

    I am using the timers to communicate after every 5 seconds, yes I am using the bt_nus_send() to communicate with the central. No, I didn't see any disconnected event either in the central or the peripheral. But I will check it again to confirm your answer.

    Thanks & Regards,

    Muhammad Usman

Reply
  • Hi Edvin,

    Thank you for the response! 

    Can you please upload both the central and peripheral applications that you are using?

    Peripherals Side FWH: ncs v2.3.0

    Multicon_inter_Reg_peri-main_Luis_V1.zip

    Central side FWH: ncs v2.0.2

    central_uart_con_202.zip

    When this happens, do you see a disconnected event either in the central or the peripheral? You say that they stop communicating. What usually triggers the communication? Is it a timer that times out? is it a button press? Is it a UART command? Are you using bt_nus_send() to communicate? Is that still being called? What does it return?

     

    I am using the timers to communicate after every 5 seconds, yes I am using the bt_nus_send() to communicate with the central. No, I didn't see any disconnected event either in the central or the peripheral. But I will check it again to confirm your answer.

    Thanks & Regards,

    Muhammad Usman

Children
  • Remember to check what bt_nus_send() returns. It may give a hint to what the issue may be. Does it return 0 or something else?

  • thank you again! i will check and update on this soon!

  • Hi Edvin!

    Thank you for your previous response! results of my testing are

    1)Sometimes, when I reset the peripheral then the central Resets itself as well

    Connection pending<CR><LF>
    <EOT><SOH><ACK><ETX><ETX>ªþ<ETB><SYN>ªþASSERTION FAIL [conn] @ WEST_TOPDIR/zephyr/subsys/bluetooth/host/gatt.c:4738<CR><LF>
    <HT> invalid parameters<CR><LF>
    <CR><LF>
    *** Booting Zephyr OS build v3.0.99-ncs1-1 ***<CR><LF>
    Starting Bluetooth Central UART example<CR><LF>
    Filters matched. Address: F7:13:07:67:2D:04 (random) connectable: yes<CR><LF>
    Connection pending<CR><LF>

    2)When i send multiple messages (25 ) from peripheral to central then central hangs to solve this i added this line 

            struct uart_data_t *buf = k_fifo_get(&fifo_uart_rx_data,
                                 K_FOREVER);
            multi_nus_send(buf);    

            k_free(buf);   // this line added in main 
    Now this issue is not occurring again.
    3)
    Remember to check what bt_nus_send() returns. It may give a hint to what the issue may be. Does it return 0 or something else?

       error1=bt_nus_send(NULL,raw_adv_data,sizeof(raw_adv_data)-20);
       
       if(error1<0) {
        printf("Failed to send data over BLE connection, error is for DK is ... %d", error1);
        //  LOG_WRN("Failed to set DSR, ret code %d", error1);

        }
     Peripheral on reset starts sending data again but not displayed the above message on no communication. Means the peripheral close the connection.  
    Any more suggestions?
    Thanks & regards,
    Muhammad Usman
  • Hello,

    Regarding 1: So you are trying to enable notifications (bt_gatt_subscribe) after the connection has terminated? Are you enabling notifications all the time? It is something you only should need to do once after the connection is established. 

    Regarding 3: Is bt_nus_send() called but is blocking? Or is it not called when it "stops responding"? Try to add some logs before and after the call to bt_nus_send(), to see whether it is stuck in there. 

    Best regards,

    Edvin

  • Hi Edvin,

    Sorry for the very late response! 

    today I started again from where I left, I attached the log of central. When the central gets stuck and stops scanning any peripheral.Although I reset both the peripherals many times . Here is the log

    00:15:16.907,012] <wrn> central_uart: ATT error code: 0x20011C0C
    [00:15:35.807,983] <inf> central_uart: Disconnected: E8:2B:FD:17:14:C2 (random) (reason 8)
    [00:15:36.953,033] <wrn> central_uart: Connecting failed
    [00:15:37.046,234] <inf> central_uart: MTU (0): 23
    [00:15:37.046,325] <inf> central_uart: Exchange pending...
    [00:15:37.046,356] <inf> central_uart: Connected: E8:2B:FD:17:14:C2 (random)
    [00:15:37.047,943] <inf> central_uart: NUS Client module initialized
    [00:15:37.159,362] <inf> central_uart: MTU exchange 0 successful (65)
    [00:15:37.906,890] <inf> central_uart: Service discovery completed
    [00:15:37.910,614] <inf> central_uart: Scanning started
    [00:15:37.910,736] <inf> central_uart: Sent to server 0: 0
    [00:15:38.106,994] <wrn> central_uart: ATT error code: 0x20011C0C
    [00:16:35.850,708] <inf> central_uart: Disconnected: F7:13:07:67:2D:04 (random) (reason 8)
    [00:16:40.990,722] <wrn> central_uart: Connecting failed
    [00:16:41.082,824] <inf> central_uart: MTU (1): 23
    [00:16:41.082,885] <inf> central_uart: Exchange pending...
    [00:16:41.082,946] <inf> central_uart: Connected: F7:13:07:67:2D:04 (random)
    [00:16:41.084,564] <inf> central_uart: NUS Client module initialized
    [00:16:41.216,796] <inf> central_uart: MTU exchange 1 successful (65)
    [00:16:41.965,148] <inf> central_uart: Service discovery completed
    [00:16:41.968,811] <inf> central_uart: Scanning started
    [00:16:41.968,963] <inf> central_uart: Sent to server 1: 1
    [00:16:42.164,489] <wrn> central_uart: ATT error code: 0x20011BC8
    [00:17:11.365,570] <inf> central_uart: Disconnected: F7:13:07:67:2D:04 (random) (reason 8)
    [00:17:14.811,920] <wrn> central_uart: Connecting failed
    [00:17:14.905,944] <inf> central_uart: MTU (1): 23
    [00:17:14.906,036] <inf> central_uart: Exchange pending...
    [00:17:14.906,066] <inf> central_uart: Connected: F7:13:07:67:2D:04 (random)
    [00:17:14.907,653] <inf> central_uart: NUS Client module initialized
    [00:17:15.016,815] <inf> central_uart: MTU exchange 1 successful (65)
    [00:17:15.864,471] <inf> central_uart: Service discovery completed
    [00:17:15.868,164] <inf> central_uart: Scanning started
    [00:17:15.868,347] <inf> central_uart: Sent to server 1: 1
    [00:17:16.164,550] <wrn> central_uart: ATT error code: 0x20011BC8
    [00:17:19.208,007] <inf> central_uart: Disconnected: E8:2B:FD:17:14:C2 (random) (reason 8)
    [00:17:19.244,537] <wrn> central_uart: Connecting failed
    [00:17:19.340,240] <inf> central_uart: MTU (0): 23
    [00:17:19.340,362] <inf> central_uart: Exchange pending...
    [00:17:19.340,362] <inf> central_uart: Connected: E8:2B:FD:17:14:C2 (random)
    [00:17:19.342,041] <inf> central_uart: NUS Client module initialized
    [00:17:19.474,395] <inf> central_uart: MTU exchange 0 successful (65)
    [00:17:20.221,954] <inf> central_uart: Service discovery completed
    [00:17:20.225,677] <inf> central_uart: Scanning started
    [00:17:20.225,799] <inf> central_uart: Sent to server 0: 0
    [00:17:20.421,997] <wrn> central_uart: ATT error code: 0x20011C0C
    [00:19:17.665,618] <inf> central_uart: Disconnected: F7:13:07:67:2D:04 (random) (reason 8)
    [00:19:20.555,419] <wrn> central_uart: Connecting failed
    [00:19:20.647,644] <inf> central_uart: MTU (1): 23
    [00:19:20.647,735] <inf> central_uart: Exchange pending...
    [00:19:20.647,766] <inf> central_uart: Connected: F7:13:07:67:2D:04 (random)
    [00:19:20.649,353] <inf> central_uart: NUS Client module initialized
    [00:19:20.831,756] <inf> central_uart: MTU exchange 1 successful (65)
    [00:19:21.679,443] <inf> central_uart: Service discovery completed
    [00:19:21.683,135] <inf> central_uart: Scanning started
    [00:19:21.683,288] <inf> central_uart: Sent to server 1: 1
    [00:19:21.879,425] <wrn> central_uart: ATT error code: 0x20011BC8
    [00:19:31.522,979] <inf> central_uart: Disconnected: E8:2B:FD:17:14:C2 (random) (reason 8)
    [00:19:32.566,619] <wrn> central_uart: Connecting failed
    [00:19:32.665,283] <inf> central_uart: MTU (0): 23
    [00:19:32.665,405] <inf> central_uart: Exchange pending...
    [00:19:32.665,435] <inf> central_uart: Connected: E8:2B:FD:17:14:C2 (random)
    [00:19:32.666,992] <inf> central_uart: NUS Client module initialized
    [00:19:32.789,398] <inf> central_uart: MTU exchange 0 successful (65)
    [00:19:33.536,956] <inf> central_uart: Service discovery completed
    [00:19:33.540,618] <inf> central_uart: Scanning started
    [00:19:33.540,740] <inf> central_uart: Sent to server 0: 0
    [00:19:33.736,999] <wrn> central_uart: ATT error code: 0x20011C0C
    [00:19:50.238,067] <inf> central_uart: Disconnected: E8:2B:FD:17:14:C2 (random) (reason 8)
    [00:19:50.787,261] <wrn> central_uart: Connecting failed
    [00:19:50.879,577] <inf> central_uart: MTU (0): 23
    [00:19:50.879,669] <inf> central_uart: Exchange pending...
    [00:19:50.879,699] <inf> central_uart: Connected: E8:2B:FD:17:14:C2 (random)
    [00:19:50.881,256] <inf> central_uart: NUS Client module initialized
    [00:19:50.989,410] <inf> central_uart: MTU exchange 0 successful (65)
    [00:19:51.736,938] <inf> central_uart: Service discovery completed
    [00:19:51.740,631] <inf> central_uart: Scanning started
    [00:19:51.740,753] <inf> central_uart: Sent to server 0: 0
    [00:19:51.936,981] <wrn> central_uart: ATT error code: 0x20011C0C
    [00:19:56.497,711] <wrn> bt_conn: Found valid connection in connected state
    [00:19:56.507,873] <wrn> bt_conn: Found valid connection in connected state
    [00:19:56.507,873] <wrn> central_uart: Connecting failed
    [00:19:59.988,037] <inf> central_uart: Disconnected: E8:2B:FD:17:14:C2 (random) (reason 8)
    [00:20:25.330,444] <inf> central_uart: Disconnected: F7:13:07:67:2D:04 (random) (reason 8)

    if you see 

    [00:19:56.497,711] <wrn> bt_conn: Found valid connection in connected state
    [00:19:56.507,873] <wrn> bt_conn: Found valid connection in connected state
    [00:19:56.507,873] <wrn> central_uart: Connecting failed
    [00:19:59.988,037] <inf> central_uart: Disconnected: E8:2B:FD:17:14:C2 (random) (reason 8)
    [00:20:25.330,444] <inf> central_uart: Disconnected: F7:13:07:67:2D:04 (random) (reason 8)

    What I understand is, that Central has info that, peripherals are already connected but in actual they are not.

    This happens when we disconnect and connect the peripheral many times continuously. Like in 1 min 4-6 times.

    These are the last lines where Central gets stuck. After resetting the central it starts scanning again. Can you please guide me regarding that?

    Thanks & Regards,

    Muhammad Usman

Related