Found valid connection in connected state

Hope you are doing good!

I am using two nrf52833DK's one as a Central and the other as a Peripheral. I am also using another custom board (nrf52833) as a second peripheral.

NCS 2.2.0 for multi NUS central and 2.3.0 for peripheral_uart

Multi-NUS (github.com/.../multi-NUS), working fine.Able to connect the two peripherals.can send and receive data. Now issues i am facing are the following.

  1. When I connect and disconnect the peripheral and connect again(repeating this step every 20 secs), the following message on RTT [00:19:51.936,981] central_uart: ATT error code: 0x20011C0C
    [00:19:56.497,711] bt_conn: Found valid connection in the connected state
    [00:19:56.507,873] bt_conn: Found valid connection in the connected state
    [00:19:56.507,873] central_uart: Connecting failed
    [00:19:59.988,037] central_uart: Disconnected: E8:2B:FD:17:14:C2 (random) (reason 8)
    [00:20:25.330,444] central_uart: Disconnected: F7:13:07:67:2D:04 (random) (reason 8)
  2. Central (Multi-NUS) becomes unresponsive. So peripheral reset has no impact on it. Need to reset the central.
    I followed the https://github.com/NordicMatt/multi-NUS/issues/1 but still the same issue as discussed.

        3. I observed the same that after 

            err = bt_conn_ctx_free(&conns_ctx_lib, conn);  // code added
            Multi-NUS unresponsive 

main.c

   

/*
 * 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 <nrfx_rtc.h>                          // RTC // code added by luis pc// code added by usman

#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 <zephyr/drivers/spi.h>
#include<zephyr/devicetree.h>
#include <zephyr/sys/printk.h>
#include <stdio.h>


#include <zephyr/drivers/gpio.h>

 uint8_t num = 0;


 int8_t Rsrp_Usigned;
const char Rsrp_Quant[16]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F};
uint8_t Central_Con_Array[6]={0xAA,0xA0,0x00,'&',')',0x00};    //(20A )0xA nrf9160 as gateway (sensor in peripheral),(20B) LTE RSSI it will be fill in nrf9160 ,(21A) BLE RSSI , (21B) simultenous connections  and last element is & ,(20,21)


uint8_t   Central_Arr[30];	
//#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 251   // 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


#define SPI_DEV_NAME "spi_3" 
#define cs  DT_ALIAS(led1)// 11 for nrf52833
#define pdn DT_ALIAS(led2)// 28 for nrf52833



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

		printk("broad cast message to : %d " ,num_nus_conns);
		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
*/

void print_uart(const struct device * dev,char *buf)
{
	int msg_len = 25; //strlen(buf);    //

	for (int i = 0; i < msg_len; i++) {
		uart_poll_out(dev, buf[i]);
	}
}

bool Data_Integrity_Check(uint8_t * Peri_Data){


 /*  printf("Data_Integrity_Check .......\n");                     

	for(char i=0; i<31; i++){											// print data coming from peripheral Via BLE , 31 bytes 					

     printf(" %x  ",Peri_Data[i]);

	}

	printf("checksum from peripheral is %x \n",Peri_Data[30]);
*/
    uint16_t crc = crc16_ccitt(0x1021,Peri_Data,30);      			 // crc polynomial 0x1021 , input arguments , Array and no. of bytes to calc checksum

    crc =(crc&0x00FF);												 //Only LSB is required 
//    printf("CRC: 0x%04X\n", crc);

	if(crc==Peri_Data[30]){										   // compare the crc calculated by received data , and the checksum send by peripheral @ index # 30 and byte # 31

	//	printf("check sum matched ....\n");

		return true;

	}

	else {
   
     printf("check sum Not matched ....\n");
       
	  return false; 
	}

   return false;

}

void Central_frame(uint8_t * Peri_Data){

	//char * index;
   
	
	uint8_t * Source_Ptr;
	uint8_t * Dest_Ptr;

	Source_Ptr = Peri_Data+11;             						 // Peri_Data(i+11);
    Dest_Ptr =   Central_Arr;									// &Central_Arr[0];             //  both are same , &Central_Arr[0]  OR  Central_Arr;


    for(char i=0; i<19; i++){

    *Dest_Ptr = *Source_Ptr;

	Dest_Ptr++;
	Source_Ptr++;

	}
  
    Central_Arr[0]=0xB0;
	Central_Arr[2]=0xB2;
    Central_Arr[3]=0xB3;
	
   /*
    printf(" Array extraction Central Array");
	for(char i=0; i<18; i++){

    printf(" %x ",Central_Arr[i]);

	}

	*/

/*	Central_Arr[0]=0xB0;
	Central_Arr[1]=Peri_Data[12];

	Central_Arr[2]=0xB2;
	Central_Arr[3]=0xB3;

	//while(*Peri_Data!=NULL){
    Central_Arr[4]=Peri_Data[15];
    Central_Arr[5]=Peri_Data[16];
	Central_Arr[6]=Peri_Data[17];

*/

	//}


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

	int err;
	bool Data_Valid;



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

		// printf("number of connections .....   %d",num);

      
		Data_Valid = Data_Integrity_Check(tx->data);                 //    Data_Integrity_Check , data is valid or not ?
        Central_frame(tx->data);
	

       
       if(Data_Valid==true){						               // if data is valid then proceed further else return, varify check sum
        
		printk("($");                                              // data send to gateway nrf9160 should be between $ (31 bytes ) &
	
	 //  err = uart_tx(uart, tx->data, tx->len, SYS_FOREVER_MS);    //send the packet to uart for nrf9160
	  //  err = uart_tx(uart, Central_Arr, 18, SYS_FOREVER_MS);    //send the packet to uart for nrf9160
    
		
	 /* for(char i=0; i<18; i++){
		   printk("%x ",Central_Arr[i]);                          // & is the last element of Central_Con_Array
		} 
    	
       */
	    
		Central_Con_Array[2]=(Central_Con_Array[2]&0xF0)|(num&0x0F);       // ( 21B)  // Nibble to write in Lower 4 bits (0xF0 = 11110000)

        for(char i=0; i<6; i++){
		//printk("0x%02X ",Central_Con_Array[i]);                          // & is the last element of Central_Con_Array
		Central_Arr[i+19]=Central_Con_Array[i];
		}
        
		//Central_Arr[22]=NULL;

		print_uart(uart,Central_Arr);                           // set the value of 25 characters , plz go inside the fn
	   }

	   else if (Data_Valid==false){                              // if data is NOT valid then NOT send the packet to uart for nrf9160

        printf("DO Nothing ...... \n");

	   }

	   k_free(tx);
		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);
	}
}


/*MTU exchange*/

static void mtu_exchange_cb(struct bt_conn *conn, uint8_t err,
			    struct bt_gatt_exchange_params *params)
{
    LOG_INF("MTU exchange %u %s (%u)", bt_conn_index(conn),
	       err == 0U ? "successful" : "failed", bt_gatt_get_mtu(conn));
}

static struct bt_gatt_exchange_params mtu_exchange_params[CONFIG_BT_MAX_CONN];

static int mtu_exchange(struct bt_conn *conn)
{
    uint8_t conn_index;
    int err;

    conn_index = bt_conn_index(conn);

    LOG_INF("MTU (%u): %u", conn_index, bt_gatt_get_mtu(conn));

    mtu_exchange_params[conn_index].func = mtu_exchange_cb;

    err = bt_gatt_exchange_mtu(conn, &mtu_exchange_params[conn_index]);
    if (err) LOG_INF("MTU exchange failed (err %d)", err);
    else LOG_INF("Exchange pending...");


    return 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;
	}

	mtu_exchange(default_conn);

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

	num++;
 
    printf("Connected.... ");



       


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

	else{


       LOG_WRN("The memory allocated for the context of this "
			"connection.");

	}

	bt_conn_unref(conn);
	default_conn = NULL;
	

	num--;

	printf("Disconnected ");
	
	
/*
	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);
	}

	printf("Start Scanning again ..... ");
*/




	
}

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

	    printk("RSSI VALUE IS %d",device_info->recv_info->rssi);

	
		Rsrp_Usigned=device_info->recv_info->rssi;   //-76 ---> 76 

		Rsrp_Usigned=(Rsrp_Usigned/6)*(-1);                   //76/6 = 12 , 

        Rsrp_Usigned=Rsrp_Quant[Rsrp_Usigned];         //Quantization range is (0-96) , divided into 16 level of 6 step each , 16*6 = 96, value will be = 0x0C

     //   printk("Rsrp_Usigned %d",Rsrp_Usigned);

		Central_Con_Array[2]=(Rsrp_Usigned<<4)|(Central_Con_Array[2]&0x0F);       // ( 21A)  // Nibble to write in upper 4 bits (0x0F = 00001111)

     //  printk("Central_Con_Array[1] %d",Central_Con_Array[1]);
}

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
};
///////////////////////////////  code added /////////////////////////////////////////

const struct device * spi_dev;
static struct spi_config spi_cfg = {
	.operation = SPI_WORD_SET(8)
	         | SPI_OP_MODE_MASTER
             | SPI_TRANSFER_MSB
            // | SPI_MODE_CPOL
            // | SPI_MODE_CPHA
             ,
	.frequency = 4000000,
	.slave = 0,
	//.cs=NULL,
};
static const struct gpio_dt_spec cs_low = GPIO_DT_SPEC_GET(cs, gpios);
static const struct gpio_dt_spec pdn_high = GPIO_DT_SPEC_GET(pdn, gpios);
static struct spi_buf rx;
const struct spi_buf_set rx_bufs = {
	.buffers = &rx,
	.count = 1
};

static struct spi_buf tx;
const struct spi_buf_set tx_bufs = {
	.buffers = &tx,
	.count = 1
};

static void spi_init(void)
{
	spi_dev = device_get_binding(SPI_DEV_NAME);

    // code added 
	   if (!spi_dev) {
        printk("SPI device not found\n");
        return;
    }

}


void Nrf21540_Write_Register()
{
    int err,ret;

   //static uint8_t tx_buffer[2] = {0xC0, 0x7D};   //  0x7D = 31 ,0x45 = 11 , 0x05
   static uint8_t tx_buffer[2] = {0xC1, 0x01};   //  enable the RX for confreg1 

    tx.buf = tx_buffer;
	tx.len = sizeof(tx_buffer);

	static uint8_t rx_buffer[2];
	rx.buf = rx_buffer;
	rx.len = sizeof(rx_buffer);

   
   
   // while (1) {

     
     ret = gpio_pin_set_dt(&cs_low,0);  // low
		if (ret < 0) {
			return;
		}
  
//err = spi_transceive(spi_dev, &spi_cfg, &tx_bufs, &rx_bufs);   //rx_bufs
 err =  spi_write(spi_dev,&spi_cfg,&tx_bufs);
	if (err < 0) {
		printf("SPI error: %d\n", err);
	} else {
	

	   printf("write successfully : %d\n", err);
		for (int i = 0; i <2; i++){
			printf(" %x",rx_buffer[i]);
			
		}

    printf("\n");
	
	}

    
  
    ret = gpio_pin_set_dt(&cs_low,1);   // high
		if (ret < 0) {
			return;
		}
   
  
  //  }
}

void Nrf21540_Read_Register()
{
    int err,ret;
 //static uint8_t tx_buffer[2] = {0x80, 0x00};   //  0x80 for reading register confreg0 ,0x8 1000 0000 for reading 
    static uint8_t tx_buffer[2] = {0x90, 0x00};   // read the  confreg1 register 

    tx.buf = tx_buffer;
	tx.len = sizeof(tx_buffer);

	static uint8_t rx_buffer[2];
	rx.buf = rx_buffer;
	rx.len = sizeof(rx_buffer);

   
     ret = gpio_pin_set_dt(&cs_low,0);  // low
		if (ret < 0) {
			return;
		}
  
err = spi_transceive(spi_dev, &spi_cfg, &tx_bufs, &rx_bufs);   //rx_bufs
    
    //err =  spi_write(spi_dev,&spi_cfg,&tx_bufs);

//err =  spi_read(spi_dev,&spi_cfg,&rx_bufs);

	if (err < 0) {
		printk("SPI error: %d\n", err);
	} else if (err==0){
	
	    printf("Read successfully : %d\n", err);
		for (int i = 0; i <2; i++){
			printf(" %x",rx_buffer[i]);
		
		}
    printf("\n");
	}

    
  
    ret = gpio_pin_set_dt(&cs_low,1);   // high
		if (ret < 0) {
			return;
		}
   
  
 
}



void main(void)
{
	int err,ret;

 //..................................... code added .......................................................


    spi_init();

	if (!device_is_ready(cs_low.port)) {
		return;
	}

	ret = gpio_pin_configure_dt(&cs_low, GPIO_OUTPUT_ACTIVE);
	ret = gpio_pin_configure_dt(&pdn_high ,GPIO_OUTPUT_ACTIVE);
	if (ret < 0) {
		return;
	}

	
 ret = gpio_pin_set_dt(&pdn_high,1);  // 0.28 nrf21540 always high 
		if (ret < 0) {
			return;
		}	

        else
         printk("PDN high at start up ...\n");

  
 //..................................... code added .......................................................

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


 // uint8_t input[18] = {0x01, 0x02, 0x03, 0x04, 0x55, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12};
  //  uint16_t crc = crc16_ccitt(0x1021,input,18);

//	 printf("CRC: 0x%04X\n", crc);
    //..................................... code added .......................................................

    Nrf21540_Write_Register();
	
    k_msleep(100);


    Nrf21540_Read_Register();
      
    k_msleep(100);



	  
  //.............................  code added .................................


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

		// Debug Variables

		k_free(buf);
	} 
}

prj.conf

#
# Copyright (c) 2018 Nordic Semiconductor
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#
CONFIG_SPI=y
CONFIG_SPI_NRFX=y

# Enable the UART driver
CONFIG_UART_ASYNC_API=y
CONFIG_NRFX_UARTE0=y
CONFIG_SERIAL=y
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y

# Enable the BLE stack with GATT Client configuration
CONFIG_BT=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_SMP=y
CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_MAX_CONN=20
CONFIG_BT_MAX_PAIRED=20
CONFIG_BT_CONN_CTX=y


# Enable the BLE modules from NCS
CONFIG_BT_NUS_CLIENT=y
CONFIG_BT_SCAN=y
CONFIG_BT_SCAN_FILTER_ENABLE=y
CONFIG_BT_SCAN_UUID_CNT=1
CONFIG_BT_GATT_DM=y
CONFIG_HEAP_MEM_POOL_SIZE=2048

# This example requires more workqueue stack
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048

# Enable bonding
CONFIG_BT_SETTINGS=y
CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y
CONFIG_NVS=y
CONFIG_SETTINGS=y

# Config logger
CONFIG_LOG=y
CONFIG_USE_SEGGER_RTT=y
CONFIG_LOG_BACKEND_RTT=y
CONFIG_LOG_BACKEND_UART=n

CONFIG_ASSERT=y

CONFIG_BT_EXT_ADV=y
CONFIG_BT_CTLR_PHY_CODED=y
CONFIG_BT_USER_PHY_UPDATE=y
CONFIG_BT_SCAN_NAME_CNT=1



#CONFIG_BT_USER_DATA_LEN_UPDATE=y
#CONFIG_BT_AUTO_DATA_LEN_UPDATE=y
#CONFIG_BT_L2CAP_TX_MTU=247
#CONFIG_BT_BUF_ACL_TX_SIZE=251
#CONFIG_BT_BUF_ACL_RX_SIZE=251
#CONFIG_BT_CTLR_DATA_LENGTH_MAX=251


Please Note:

I tried with original example as well without any code addition 

NCS 1.4.1 for multi NUS central & peripheral_uart both.

But still get the same issue as discussed above .

Thanks in Advance,
Regards,

  • Hello Muhammad,

    It seems that the sample you are referring to is extremely old. I recommend against using it as is. Instead, could you please follow the steps in Matt's blog post and update a Central UART sample to support multiple connections instead?

    Hieu

  • Hello Hieu!

    Thank you for your response!

    Yes, i followed that, and was able to test Multi NUS with NCS version 2.2.0 and peripheral_Uart NCS version 2.3.0. I am facing issues with these versions.

    The reason to test it with 1.4.1 was that, as it was original and recommended so I tested it with NCS 1.4.1 to make sure switching to the latest 2.2.0 version is correct.

    Multi  NUS is behaving the same way in both versions 1.4.1 and 2.2.0 .

    Can you please help me in this regard?

    Thanks in Advance !

  • Hello Muhammad,

            3. I observed the same that after 

                err = bt_conn_ctx_free(&conns_ctx_lib, conn);  // code added
                Multi-NUS unresponsive 

    Have you checked if if there are error code returned here? If yes, what is it?

  • Hello Hieu!

    Thank You so much for your support!

    Have you checked if if there are error code returned here? If yes, what is it?

    Sorry, No error code after that. So I did some more testing to observe.

    Today, after some more experiments. What i observed is that, if I reset the peripheral just after it gets connected with central then the above issue occurs. But if I wait for 10 seconds then it works fine!

    Do you know what is the reason behind it?

    And one more question to ask, from which file will I get the error code meaning?

    Thanks & Regards,

    Muhammad Usman

  • Hi Muhammad,

    Are you certain that the main.c file you shared can be used with NCS v2.2.0?

    If I use it as is, then I ran into an issue where log_strdup() was undefined.

    If I remove the use of log_strdup(), I can build. However, I quickly found that the application crashed immediately as soon as it started with the following log:

    00> [00:00:00.025,177] <err> os:  xpsr:  0x61000000
    00> [00:00:00.025,207] <err> os: Faulting instruction address (r15/pc): 0x82f7e5b4
    00> [00:00:00.025,238] <err> os: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0
    00> [00:00:00.025,268] <err> os: Current thr[00:00:00.[00:00:00.015,502] <inf> fs_nvs: alloc wra: 0, fe8
    00> [00:00:00.015,502] <inf> fs_nvs: data wra: 0, 0
    00> [00:00:00.015,655] <inf> sdc_hci_driver: SoftDevice Controller build revision: 
    00>                                          6d 90 41 2a 38 e8 ad 17  29 a5 03 38 39 27 d7 85 |m.A*8... )..89'..
    00>                                          1f 85 d8 e1                                      |....             
    00> [00:00:00.019,653] <inf> bt_hci_core: No ID address. App must call settings_load()
    00> [00:00:00.019,653] <inf> central_uart: Bluetooth initialized
    00> [00:00:00.020,233] <dbg> central_uart: uart_cb: UART_RX_BUF_REQUEST
    00> [00:00:00.020,324] <inf> central_uart: NUS Client module initialized
    00> [00:00:00.025,177] <err> os: ***** BUS FAULT *****
    00> [00:00:00.025,207] <err> os:   Instruction bus error
    00> [00:00:00.025,238] <err> os: r0/a1:  0x00000000  r1/a2:  0x200006d0  r2/a3:  0x0003bfc8
    00> [00:00:00.025,238] <err> os: r3/a4:  0x00000000 r12/ip:  0x0002b9d5 r14/lr:  0x00018c69
    00> [00:00:00.025,268] <err> os:  xpsr:  0x61000000
    00> [00:00:00.025,299] <err> os: Faulting instruction address (r15/pc): 0x82f7e5b4
    00> [00:00:00.025,329] <err> os: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0
    00> [00:00:00.025,360] <err> os: Current thread: 0x20005c88 (unknown)
    00> [00:00:00.494,232] <err> fatal_error: Resetting system


    Muhammad Usman said:

    Today, after some more experiments. What i observed is that, if I reset the peripheral just after it gets connected with central then the above issue occurs. But if I wait for 10 seconds then it works fine!

    Do you know what is the reason behind it?

    What events are you referring to with the 10 seconds wait here? I thought the original post says that you wait 20 seconds after the connection is established before you disconnect it?

    If you make the disconnection happen by resetting, then the connection has to timeout first. Before that, the first connection is still considered connected, which would explain the "Found valid connection in the connected state" warning you had.

    That might not explain the crash or unresponsive behavior though. I think the "reconnected" connection would just be treated simply as a new third connection.

    I have an inkling it has something to do with getting the correct Connection Context entry during the discovery process.

    Could you please put in some log lines as I described below, and give me the log when the issue happened?

    • Include the function name
    • If the function takes a struct bt_conn *conn as a parameter, include the conn pointer value
    • In connected():
      • At the end of the function, please log the value of nus_client
    • In gatt_discover():
      • At the end of the function, please log the value of nus_client
    • In discovery_complete():
      • After the if(ctx->data == nus) line, please log the value of
        • nus
        • i

    In addition to the log, please also share the main.c file after you have made the modifications.

    Please also try with once with CONFIG_LOG_MODE_IMMEDIATE and once CONFIG_LOG_MODE_MINIMAL.

    The reason is that log mode Immediate will produce the log right away and give us all the information even if the system crash. However, as we are adding log into handler, that delays the handler, and can cause timing issues and is a cause of failure.

    Therefore, another test with log mode Minimal will help rule that out when we cross check the issue.

    Regards,

    Hieu

Related