<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Simultanious data reading from connected devices to central.</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/96849/simultanious-data-reading-from-connected-devices-to-central</link><description>Hi, 
 I am working in Nrf52832, Zephyr as central for connecting multiple peripheral devics. I want to read the multiple devices data at a same time. I am using common discovery function for all devices. And I use delayed work queue for conntion update</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Thu, 23 Feb 2023 14:40:28 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/96849/simultanious-data-reading-from-connected-devices-to-central" /><item><title>RE: Simultanious data reading from connected devices to central.</title><link>https://devzone.nordicsemi.com/thread/411699?ContentTypeID=1</link><pubDate>Thu, 23 Feb 2023 14:40:28 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:0c525c8d-d6cf-459b-b083-5d177a2cb263</guid><dc:creator>Einar Thorsrud</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;I am looking more at your code now, and I see I was too quick earlier. You do connect to multiple devices, and from what I can see, you subscribe from notifications from all of them. And from the printout from earlier I see you also get notifications from at least two of them (that is all that log shows).&lt;/p&gt;
&lt;p&gt;I do not see the source of all the lines in the log in the code, so it has probably evolved a bit, but form what I can see it does not seem like you disconnect o stop subscribing to notifications on the first when you connect to the second, so I would expect you to still get notifications from the first when connected to the second. Does that noe happen? And is that the case? If so, can you check that there is no disconnect?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Simultanious data reading from connected devices to central.</title><link>https://devzone.nordicsemi.com/thread/411294?ContentTypeID=1</link><pubDate>Wed, 22 Feb 2023 09:52:22 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:d643e1dc-724f-47c8-b675-de7894631384</guid><dc:creator>ATHULYA SHAJI</dc:creator><description>&lt;p&gt;How to work multiple notification in central side&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Athulya&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Simultanious data reading from connected devices to central.</title><link>https://devzone.nordicsemi.com/thread/411080?ContentTypeID=1</link><pubDate>Tue, 21 Feb 2023 11:40:01 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:17fa18f2-c310-4f9c-b145-a06d3748a4c5</guid><dc:creator>Einar Thorsrud</dc:creator><description>&lt;p&gt;What do you mean by simultaniously? There is only one radio, and one CPU, so it canot happen at exactly the same time. And the BLE connections will have connection events, and the communication with every peer has to start at that event. So there is no way to get this done exactly at the same time.&lt;/p&gt;
&lt;p&gt;But it is possible to be connected at multiple peripherals at the same time, which I see from the code and the log here that you are not. For that, I suggest you take a look at the multilink central sample that I linked to. Essentially, when connected, just start scanning again and you can be connected to multiple peripherals at once (provided the connection parameters have enough slack,&amp;nbsp; you configure support for more peripherals as in the sample, and you handel it (as in the sample).&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Simultanious data reading from connected devices to central.</title><link>https://devzone.nordicsemi.com/thread/411039?ContentTypeID=1</link><pubDate>Tue, 21 Feb 2023 08:58:19 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:17322712-42fd-408b-84a8-de3f8999b87a</guid><dc:creator>ATHULYA SHAJI</dc:creator><description>&lt;p&gt;I try to make more than one connection and I want to data from each connected devices simultaneously. But Now I get result like this.&lt;/p&gt;
&lt;p&gt;&lt;img style="max-height:240px;max-width:320px;" src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1676969756003v4.png" alt=" " /&gt;&lt;/p&gt;
&lt;p&gt;But actually I want both the data are simultaneously.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Simultanious data reading from connected devices to central.</title><link>https://devzone.nordicsemi.com/thread/411033?ContentTypeID=1</link><pubDate>Tue, 21 Feb 2023 08:43:06 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:31e97141-948f-4100-bac9-48903ba2d5b4</guid><dc:creator>Einar Thorsrud</dc:creator><description>&lt;p&gt;Looking at this briefly it does not look like you are trying to make more than one connection? Perhaps I misunderstood what you want to do. Can you elaborate on what you want to do, what you are implementing it the way you are, and in what way it is not working?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Simultanious data reading from connected devices to central.</title><link>https://devzone.nordicsemi.com/thread/411030?ContentTypeID=1</link><pubDate>Tue, 21 Feb 2023 08:37:26 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:072d5864-9b6f-4c19-9466-fe20eaa17c7e</guid><dc:creator>ATHULYA SHAJI</dc:creator><description>&lt;p&gt;main.c&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;/*
 * Copyright (c) 2012-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include &amp;quot;main.h&amp;quot;

int dev_type;
uint8_t pMAC[6];
bool Discovered = false;
uint8_t conn_count = 0;

char central_pool[512] = {};
driver_inst_t *gen_drivers[CONFIG_BT_MAX_CONN] = {};
char d_name[16];
struct bt_conn *conn_in_progress;
struct bt_gatt_discover_params discover_params;
static struct bt_uuid_16 uuid;

volatile bool should_connect = true;

static ble_state_e g_main_state;

#define UART_DEVICE_NODE DT_NODELABEL(uart0)
static const struct device *uart_dev = DEVICE_DT_GET(UART_DEVICE_NODE);

K_MSGQ_DEFINE(todo, 36, 32, 4);

//struct k_delayed_work conn_work, sec_work, kill_work;
struct k_mutex my_mutex;

//Test
int i=-1;
//

/* size of stack area used by each thread */
#define STACKSIZE 1024

/* scheduling priority used by each thread */
#define PRIORITY 0

void send_data_pkt(uint8_t *pkt, uint16_t len)
{
  for (int i = 0; i &amp;lt; len; i++) {
		uart_poll_out(uart_dev, pkt[i]);
	}
}

void main_set_ble_state(ble_state_e state)
{
  g_main_state = state;
}

static uint16_t heartrate_main_init(void)
{

  heartrate_init((driver_inst_t *)gen_drivers[i], d_name);
}

static uint16_t wellue_main_init(void)
{

  wellue_init((driver_inst_t *)gen_drivers[i], d_name);
}

static uint16_t and_main_init(void)
{
  //auth_cb_display.passkey_entry = passkey_entry;
  and_init((driver_inst_t *)gen_drivers[i], d_name);
}

static uint8_t svc_discover_func(struct bt_conn *conn,
                                 const struct bt_gatt_attr *attr,
                                 struct bt_gatt_discover_params *params)
{
  k_mutex_lock(&amp;amp;my_mutex, K_FOREVER);
  uint8_t ret;
  
  if (!attr)
  {
    //printk(&amp;quot;Discover complete\n&amp;quot;);
    (void)memset(params, 0, sizeof(*params));
    generic_on_svc_disc_evt(gen_drivers[i], 0);
    goto done;
  }

   //printk(&amp;quot;[SERVICE] handle %x\n&amp;quot;, attr-&amp;gt;handle);

  if (generic_on_svc_disc_evt(gen_drivers[i], attr))
  {
    // printk(&amp;quot;Found service\n&amp;quot;);
  }

  ret = BT_GATT_ITER_CONTINUE;

done:
  return ret;
  k_mutex_unlock(&amp;amp;my_mutex);
}

static uint8_t char_discover_func(struct bt_conn *conn,
                                  const struct bt_gatt_attr *attr,
                                  struct bt_gatt_discover_params *params)
{
  k_mutex_lock(&amp;amp;my_mutex, K_FOREVER);
  uint8_t ret;
  if (!attr)
  {

    // printk(&amp;quot;Char discovery complete\n&amp;quot;);
    memset(params, 0, sizeof(*params));
    generic_on_char_disc_evt(gen_drivers[i], attr);
    ret = BT_GATT_ITER_STOP;
    goto done;
  }

  // printk(&amp;quot;[ATTRIBUTE] handle %x\n&amp;quot;, attr-&amp;gt;handle);
  if (generic_on_char_disc_evt(gen_drivers[i], attr))
  {
    // printk(&amp;quot;Found characteristic\n&amp;quot;);
  }

  ret = BT_GATT_ITER_CONTINUE;
done:
  k_mutex_unlock(&amp;amp;my_mutex);
  return ret;
}

static uint8_t cccd_discover_func(struct bt_conn *conn,
                                  const struct bt_gatt_attr *attr,
                                  struct bt_gatt_discover_params *params)
{
  k_mutex_lock(&amp;amp;my_mutex, K_FOREVER);
  uint8_t ret;
  if (!attr)
  {
    // printk(&amp;quot;[CCCD] discovery complete\n&amp;quot;);
    memset(params, 0, sizeof(*params));
    generic_on_cccd_disc_evt(gen_drivers[i], attr);
    ret = BT_GATT_ITER_STOP;
    goto done;
  }

  // printk(&amp;quot;[CCCD] handle %x\n&amp;quot;, attr-&amp;gt;handle);
  if (generic_on_cccd_disc_evt(gen_drivers[i], attr))
  {
    // printk(&amp;quot;Found cccd\n&amp;quot;);
  }

  ret = BT_GATT_ITER_CONTINUE;
done:
  k_mutex_unlock(&amp;amp;my_mutex);
  return ret;
}

void start_char_discovery(struct bt_conn *conn, uint16_t start_handle, uint16_t end_handle)
{
  // printk(&amp;quot;Char Start Handle %x - End Handle %x\n&amp;quot;, start_handle, end_handle);
  discover_params.start_handle = start_handle;
  discover_params.end_handle = end_handle;
  discover_params.func = char_discover_func;
  discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
  bt_gatt_discover(conn, &amp;amp;discover_params);
}

void start_cccd_discovery(driver_inst_t *inst, uint16_t start_handle, uint16_t end_handle)
{
  // printk(&amp;quot;CCCD Start Handle %x - End Handle %x\n&amp;quot;, start_handle, end_handle);
  struct bt_conn *conn = inst-&amp;gt;conn;
  start_handle--;
  if (inst-&amp;gt;common-&amp;gt;init-&amp;gt;quirks &amp;amp; QUIRK_FIND_INFO_BOUNDS)
    end_handle++;
  memcpy(&amp;amp;uuid, BT_UUID_GATT_CCC, sizeof(uuid));
  discover_params.uuid = &amp;amp;uuid.uuid;
  discover_params.start_handle = start_handle;
  discover_params.end_handle = end_handle;
  discover_params.func = cccd_discover_func;
  discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
  bt_gatt_discover(conn, &amp;amp;discover_params);
}

static struct bt_gatt_subscribe_params subscribe_params[UUID_MAX];

void subscribe(struct bt_conn *conn, uint16_t handle, uint16_t value_handle, uint16_t value, bt_gatt_notify_func_t notify_func, int cccd_index)
{
  subscribe_params[cccd_index].notify = notify_func;
  subscribe_params[cccd_index].value = value;
  subscribe_params[cccd_index].value_handle = value_handle;
  subscribe_params[cccd_index].ccc_handle = handle;

  int err = bt_gatt_subscribe(conn, &amp;amp;subscribe_params[cccd_index]);
  if (err &amp;amp;&amp;amp; err != -EALREADY)
  {
    //printk(&amp;quot;Subscribe failed (err %d)\n&amp;quot;, err);
  }
  else
  {
    //printk(&amp;quot;[SUBSCRIBED] %x %x %x\n&amp;quot;, handle, value_handle, value);
  }
}

static void initialize_discovery(struct bt_conn *conn)
{
  if (Discovered)
  {
    //printk(&amp;quot;Already discovered\n&amp;quot;);
    return true;
  }
  Discovered = true;
  //printk(&amp;quot;Starting discovery\n&amp;quot;);

  //Presdiscovered //Comment test
  // if (gen_drivers[0]-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[0].handle)
  // {
  //   //printk(&amp;quot;Using prediscovery\n&amp;quot;);
     //generic_prediscover(gen_drivers[0]);
  //   return;
  // }
//
  discover_params.uuid = 0;
  discover_params.func = svc_discover_func;
  discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
  discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
  discover_params.type = BT_GATT_DISCOVER_PRIMARY;

  int err = bt_gatt_discover(conn, &amp;amp;discover_params);
  if (err)
  {
    //printk(&amp;quot;Discover failed(err %d)\n&amp;quot;, err);
    return;
  }
  else
  {
    //printk(&amp;quot;initialize_discovery success\n&amp;quot;);
  }
}


static void connected(struct bt_conn *conn, uint8_t err)
{
  //k_mutex_lock(&amp;amp;my_mutex, K_FOREVER); //TEST COMMENTED
//TEST
i++;
printk(&amp;quot;Value of i=%d\n&amp;quot;,i);
//
  gen_drivers[i] = (driver_inst_t *)central_pool;
  // printk(&amp;quot;Connecting type %d - Size of object %d\n&amp;quot;, dev_type, sizeof(driver_init_t));
  gen_drivers[i]-&amp;gt;conn = conn;
  //i++;
  // conn_in_progress = 0;

  char addr[BT_ADDR_LE_STR_LEN];
  const bt_addr_le_t *daddr = bt_conn_get_dst(conn);
  memcpy(pMAC, daddr-&amp;gt;a.val, 6);
  bt_addr_le_to_str(daddr, addr, sizeof(addr));
  main_set_ble_state(BLE_STATE_CONNECTED);
  if (err)
  {
    printk(&amp;quot;Failed to connect to %s (%u)\n&amp;quot;, addr, err);

    bt_conn_unref(conn_in_progress);
    conn_in_progress = NULL;

    start_scan();
    return;
  }
  conn_in_progress = NULL;
  conn_count++;
  if (conn_count &amp;lt;CONFIG_BT_MAX_CONN)
  {
    start_scan();
  }
  printk(&amp;quot;Connected (%u): %s\n&amp;quot;, conn_count, addr);
  switch (dev_type)
  {
  case RENPHOSCALE_TYPE:
    heartrate_main_init();
    initialize_discovery(conn);
    break;
  case WELLUE_TYPE:
    wellue_main_init();
    initialize_discovery(conn);
    break;
  case AND_TYPE:
    and_main_init();
    initialize_discovery(conn);
    break;
  default:
    break;
  }
  
done:
  k_mutex_unlock(&amp;amp;my_mutex);
}

static void disconnected(struct bt_conn *conn, uint8_t reason)
{
  char addr[BT_ADDR_LE_STR_LEN];

  k_mutex_lock(&amp;amp;my_mutex, K_FOREVER);

  bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

  printk(&amp;quot;Disconnected: %s (reason 0x%02x)\n&amp;quot;, addr, reason);

  // if (!conn)
  // {
  //   return;
  // }

  bt_conn_unref(conn);
  conn = NULL;
  if (conn_count &amp;lt; CONFIG_BT_MAX_CONN)
  {
    // printk(&amp;quot;conn_cont=%d&amp;quot;,conn_count);
    //gScanning = false;
    start_scan();
  }
  //conn_count--;
  // if ((conn_count == 1U)) {
	// 	start_scan();
	// }
  conn_count--;
done:
  k_mutex_unlock(&amp;amp;my_mutex);
}
bool gScanning = false;

bool start_scan()
{
  if (gScanning)
  {
    printk(&amp;quot;Scanning already running\n&amp;quot;);
    return true;
  }
  int err;

  /* Use active scanning and disable duplicate filtering to handle any
   * devices that might update their advertising data at runtime. */
  struct bt_le_scan_param scan_param = {
      .type = BT_LE_SCAN_TYPE_ACTIVE,
      .options = BT_HCI_LE_SCAN_FILTER_DUP_DISABLE,
      .interval = 300,
      .window = 290,
  };

  err = bt_le_scan_start(&amp;amp;scan_param, device_found); // Call back function

  if (err)
  {
    printk(&amp;quot;Scanning failed to start (err %d)\n&amp;quot;, err);
    return;
  }

  printk(&amp;quot;Scanning successfully started............................................\n&amp;quot;);

  #if 0
  err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad),
                        sd, ARRAY_SIZE(sd));
  if (err)
  {
    printk(&amp;quot;Advertising failed to start (err %d)\n&amp;quot;, err);
    return false;
  }
#endif

  gScanning = true;
  return true;
}

static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
{
  char addr[BT_ADDR_LE_STR_LEN];

  bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

  // printk(&amp;quot;LE conn param req: %s int (0x%04x, 0x%04x) lat %d to %d\n&amp;quot;,
  //        addr, param-&amp;gt;interval_min, param-&amp;gt;interval_max, param-&amp;gt;latency,
  //        param-&amp;gt;timeout);

  return true;
}

static void le_param_updated(struct bt_conn *conn, uint16_t interval,
                             uint16_t latency, uint16_t timeout)
{
  char addr[BT_ADDR_LE_STR_LEN];

  bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

  k_mutex_lock(&amp;amp;my_mutex, K_FOREVER);
 

  if (dev_type == AND_TYPE)
  {
    int err = bt_conn_set_security(conn, BT_SECURITY_L2);
    if (err)
    {
      printk(&amp;quot;Failed to set security\n&amp;quot;);
    }
    else
    {
      //printk(&amp;quot;bt_conn_set_security -&amp;gt; BT_SECURITY_L2\n&amp;quot;);
    }
  }
  else
  {
    
    initialize_discovery(conn);
  }

  // initialize_discovery();
done:
  k_mutex_unlock(&amp;amp;my_mutex);
}

static void security_changed(struct bt_conn *conn, bt_security_t level,
			     enum bt_security_err err)
{
  k_mutex_lock(&amp;amp;my_mutex, K_FOREVER);
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	if (!err) {
		//printk(&amp;quot;Security changed: %s level %u&amp;quot;, addr, level);
	} else {
		printk(&amp;quot;Security failed: %s level %u err %d&amp;quot;, addr,
			level, err);
	}
  done:
   k_mutex_unlock(&amp;amp;my_mutex);
}
static struct bt_conn_cb conn_callbacks = {
    .connected = connected,
    .disconnected = disconnected,
    .le_param_req = le_param_req,
    .le_param_updated = le_param_updated,
    .security_changed = security_changed,

};

/* Bluetooth initialization*/
static void bt_ready(int err)
{

  if (err)
  {
    printk(&amp;quot;Bluetooth init failed (err %d)\n&amp;quot;, err);
    return;
  }

  printk(&amp;quot;Bluetooth initialized\n&amp;quot;);

  heartrate_reserve();
  wellue_reserve();
  and_reserve();

  bt_conn_cb_register(&amp;amp;conn_callbacks);


  main_set_ble_state(BLE_STATE_SCANNING);
  start_scan();
}
// K_MUTEX_DEFINE(my_mutex);
static void conn_update(struct k_work *work)
{
  // printk(&amp;quot;Forcing end of connect\n&amp;quot;);

  if (conn_in_progress)
  {
    // printk(&amp;quot;Fo real\n&amp;quot;);
    bt_conn_disconnect(conn_in_progress, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
    conn_in_progress = 0;
    should_connect = true;
  }
}


void main(void)
{

  int err;
  k_mutex_init(&amp;amp;my_mutex);

  if (!device_is_ready(uart_dev)) {
		//printk(&amp;quot;UART device not found!&amp;quot;);
		return;
	}
  err = bt_enable(bt_ready);  
}

// TEST
// K_THREAD_DEFINE(discovery_id, STACKSIZE, initialize_discovery, NULL, NULL, NULL,
// 		PRIORITY, 0, 0);
    &lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;scan.c&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;
#include &amp;quot;main.h&amp;quot;
#include &amp;quot;generic.h&amp;quot;

bool need_connect = false;
struct bt_conn *default_conn;
	
/* List all the devices arround the central device*/
void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
			 struct net_buf_simple *ad)
{
 	//k_mutex_lock(&amp;amp;my_mutex, K_FOREVER);
	bool need_connect =false;
	struct bt_conn_le_create_param create_param = {
		.options = BT_CONN_LE_OPT_NONE,
		.interval = INIT_INTERVAL,
		.window = INIT_WINDOW,
		.interval_coded = 0,
		.window_coded = 0,
		.timeout = 0,
	};
	struct bt_le_conn_param conn_param = {
		.interval_min = CONN_INTERVAL,
		.interval_max = CONN_INTERVAL,
		.latency = CONN_LATENCY,
		.timeout = CONN_TIMEOUT,
	};
	
	if(conn_in_progress){
		return;
	}
	char name[40];
	strcpy(name, ad-&amp;gt;data);
	if(strstr(name,&amp;quot;QN-Scale&amp;quot;)!=NULL)
    {
		need_connect =true;
        dev_type = RENPHOSCALE_TYPE;
        printk(&amp;quot;Weighting Mechine found.....................\n&amp;quot;);
    }
	else if (strstr(name,&amp;quot;VTM 20F&amp;quot;)!=NULL)
	{
		   need_connect =true;
           dev_type = WELLUE_TYPE;
		   printk(&amp;quot;Pulse Oximeter device found.....................\n&amp;quot;);
	}
	else if (ad-&amp;gt;len == 13)
	{
		need_connect = true;
		dev_type = AND_TYPE;
		printk(&amp;quot;A&amp;amp;D Medical device found.....................\n&amp;quot;);
	}
	
	if(need_connect)
	{
		Discovered = false;
		int err = bt_le_scan_stop();
		if (err)
		{
			printk(&amp;quot;Stop LE scan  (err %d)\n&amp;quot;, err);
		}
		gScanning = false;
		uint8_t strAddr[BT_ADDR_LE_STR_LEN];
		bool res = bt_conn_exists_le(BT_ID_DEFAULT, addr);
		bt_addr_le_to_str(addr, strAddr, sizeof(strAddr));
		//printk(&amp;quot;Address %s\n&amp;quot;, strAddr);
		if (res)
		{
			conn_in_progress = bt_conn_lookup_addr_le(BT_ID_DEFAULT, addr);
			err = bt_conn_disconnect(conn_in_progress, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
		}

		err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT,&amp;amp;conn_in_progress);
		if(err)
		{
			printk(&amp;quot;Error code of bt_conn_le_create %d\n&amp;quot;, err);
			start_scan();
    		return false;
		}
		

	return true;
	}
 	
   done:
      k_mutex_unlock(&amp;amp;my_mutex);
}
		&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;generic.c&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;#include &amp;quot;main.h&amp;quot;

uint16_t nchar;

uint32_t generic_uuid_register(driver_common_t *common, const driver_init_t *init)
{
  common-&amp;gt;init = init;
  return NRF_SUCCESS;
}

uint32_t generic_inst_init(driver_inst_t *inst, const driver_common_t *common, const char *name)
{
      int ret = NRF_SUCCESS;

  inst-&amp;gt;common = common;
  inst-&amp;gt;discovered = false;
  inst-&amp;gt;current_svc = -1;
  inst-&amp;gt;current_char = -1;
  inst-&amp;gt;current_cccd = -1;
  inst-&amp;gt;new_bond = false;
  memcpy(inst-&amp;gt;name, name, sizeof(inst-&amp;gt;name));

  for (int i = 0; i &amp;lt; common-&amp;gt;init-&amp;gt;nuuids; i++)
  {
    inst-&amp;gt;char_handles[i] = BLE_GATT_HANDLE_INVALID;
    inst-&amp;gt;cccd_handles[i] = BLE_GATT_HANDLE_INVALID;
    inst-&amp;gt;serv_handles[i] = BLE_GATT_HANDLE_INVALID;
    inst-&amp;gt;serv_ehandles[i] = 0xFFFF;
    inst-&amp;gt;char_ehandles[i] = 0xFFFF;
  }
  if (ret == NRF_SUCCESS &amp;amp;&amp;amp; common-&amp;gt;init-&amp;gt;init_func)
  {
    common-&amp;gt;init-&amp;gt;init_func(inst);
  }
 
  return ret;
  
}
void generic_on_timeout(driver_inst_t *inst)
{
  if (inst-&amp;gt;common-&amp;gt;init-&amp;gt;timeout_func)
  {
    inst-&amp;gt;common-&amp;gt;init-&amp;gt;timeout_func(inst);
  }
}
uint32_t generic_prediscover(driver_inst_t *inst)
 {
   for (int i = 0; i &amp;lt; inst-&amp;gt;common-&amp;gt;init-&amp;gt;nuuids; i++)
   {
     inst-&amp;gt;char_handles[i] = inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].handle;
     inst-&amp;gt;cccd_handles[i] = inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].cccd_handle;
     inst-&amp;gt;serv_handles[i] = inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].handle;
   }
   generic_enable_notif(inst);
 }

static uint16_t get_handle_by_name(driver_inst_t *inst, int name)
{
  //Check if this uuid is one we need to save
  for (int j = 0; j &amp;lt; inst-&amp;gt;common-&amp;gt;init-&amp;gt;nuuids; j++)
  {
    if (inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[j].name == name)
    {
      return inst-&amp;gt;char_handles[j];
    }
  }
  return -1;
}
static uint32_t send_pkt_without_resp(driver_inst_t *inst, uint16_t handle_ept, const uint8_t *data, uint8_t len)
{

  bt_gatt_write_without_response(inst-&amp;gt;conn, handle_ept, data, len, false);
  return NRF_SUCCESS;
}
uint32_t generic_send_pkt_without_resp(driver_inst_t *inst, int name, const uint8_t *data, uint8_t len)
{
  uint16_t handle = get_handle_by_name(inst, name);
  return send_pkt_without_resp(inst, handle, data, len);
}

static  uint8_t notify_func(struct bt_conn *conn,
		struct bt_gatt_subscribe_params *params,
		const void *data, uint16_t length)
{

    uint8_t ret;
		//printk(&amp;quot;[NOTIFICATION] data %u length %u\n&amp;quot;, data, length);

  driver_inst_t *inst = 0;
  for (int i = 0; i &amp;lt; MAX_D; i++)
  {
    if (!gen_drivers[i]){
      continue;
    }
    if (gen_drivers[i]-&amp;gt;conn != conn){
      continue;
    }
    inst = gen_drivers[i];
  }

     ret = BT_GATT_ITER_STOP;
  if (!inst)
  {
    //printk(&amp;quot;Notify func: failed to find conn\n&amp;quot;);
     goto done;
  }

  if (!data)
  {
    
    if (length)
    {
      //printk(&amp;quot;[SUBSCRIBED]\n&amp;quot;);
      ret = BT_GATT_ITER_STOP;
       goto done;
    }
    //printk(&amp;quot;[UNSUBSCRIBED]\n&amp;quot;);
    params-&amp;gt;value_handle = 0;
    ret = BT_GATT_ITER_STOP;
     goto done;
   }

  int name = inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[nchar].name;

  if (inst-&amp;gt;common-&amp;gt;init-&amp;gt;hvx_func)
  {
    inst-&amp;gt;common-&amp;gt;init-&amp;gt;hvx_func(inst, name, data, length);
  }
   ret=BT_GATT_ITER_CONTINUE;
done:
  return ret;
}

// static u8_t read_func(struct bt_conn *conn, int err,
//                       struct bt_gatt_read_params *params,
//                       const void *data, u16_t len, u16_t nchar)
// {
//   k_mutex_lock(&amp;amp;gen_mutex, K_FOREVER);
//   driver_inst_t *inst = 0;
//   for (int i = 0; i &amp;lt; MAX_D; i++)
//   {
//     if (!gen_drivers[i])
//       continue;
//     if (g_drivers[i]-&amp;gt;conn != conn)
//       continue;
//     inst = gen_drivers[i];
//   }

//   if (!inst)
//   {
//     printk(&amp;quot;Notify func: failed to find conn\n&amp;quot;);
//     goto done;
//   }

//   int name = inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[nchar].name;

//   printk(&amp;quot;[READ_RSP] idx %d\n&amp;quot;, name);

//   if (inst-&amp;gt;common-&amp;gt;init-&amp;gt;hvx_func)
//   {
//     inst-&amp;gt;common-&amp;gt;init-&amp;gt;hvx_func(inst, name, data, len);
//   }
// done:
//   k_mutex_unlock(&amp;amp;gen_mutex);
//   return BT_GATT_ITER_STOP;
// }

#define NOTIFY(n)                                                        \
  static uint8_t notify##n(struct bt_conn *conn,                         \
                        struct bt_gatt_subscribe_params *params,         \
                        const void *data, uint16_t length)               \
  {                                                                      \
    return notify_func(conn, params, data, length);                      \
  }

// #define RDECLS(n)                                         \
//   static u8_t read##n(struct bt_conn *conn, u8_t err,     \
//                       struct bt_gatt_read_params *params, \
//                       const void *data, u16_t length)     \
//   {                                                       \
//     return read_func(conn, err, params, data, length, n); \
//   }

NOTIFY(0);
NOTIFY(1);
NOTIFY(2);
NOTIFY(3);
NOTIFY(4);
NOTIFY(5);
// RDECLS(0);
// RDECLS(1);
// RDECLS(2);
// RDECLS(3);
// RDECLS(4);
static const bt_gatt_notify_func_t nfuncs[UUID_MAX]={notify0,notify1,notify2,notify3,notify4,notify5};
//static const bt_gatt_read_func_t rfuncs[UUID_MAX] = {read0, read1, read2, read3, read4 };

static struct bt_gatt_read_params params[UUID_MAX];

void generic_enable_notif(driver_inst_t *inst)
{
  if (inst-&amp;gt;discovered)
    return;

  //printk(&amp;quot;Notifications enabled\n&amp;quot;);

  for (int i = inst-&amp;gt;current_cccd + 1; i &amp;lt; inst-&amp;gt;common-&amp;gt;init-&amp;gt;nuuids; i++)
  {
    if (inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].cccd &amp;amp;&amp;amp; (inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].donotsubscribe == 0))
    {
      inst-&amp;gt;current_cccd = i;

      subscribe(inst-&amp;gt;conn, inst-&amp;gt;cccd_handles[i], inst-&amp;gt;char_handles[i], inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].cccd, nfuncs[i], i);

    }
  }

  inst-&amp;gt;discovered = true;
  if (inst-&amp;gt;common-&amp;gt;init-&amp;gt;connect_func != NULL)
  {
    inst-&amp;gt;common-&amp;gt;init-&amp;gt;connect_func(inst);
  }
}

void generic_enable_notif_for_handle(driver_inst_t *inst, int name, bool indicate)
{
  if (indicate)
  {
    subscribe(inst-&amp;gt;conn, inst-&amp;gt;cccd_handles[name], inst-&amp;gt;char_handles[name], BLE_GATT_HVX_INDICATION, nfuncs[name], name);
  }
  else
  {
    subscribe(inst-&amp;gt;conn, inst-&amp;gt;cccd_handles[name], inst-&amp;gt;char_handles[name], BLE_GATT_HVX_NOTIFICATION, nfuncs[name], name);
  }
}

bool compare_uuids(const u_t *a, const u_t *b, uint16_t mask)
{
  
  if (a-&amp;gt;uuid.type != b-&amp;gt;uuid.type)
    return false;
  if (a-&amp;gt;uuid.type == BT_UUID_TYPE_16)
    return memcmp(&amp;amp;a-&amp;gt;u16.val, &amp;amp;b-&amp;gt;u16.val, 2) == 0;

  if (memcmp(a-&amp;gt;u128.val, b-&amp;gt;u128.val, 16) != 0)
  {
    return false;
  }
  return true;
}

bool scan_chars(driver_inst_t *inst, int svc)
{
  inst-&amp;gt;current_svc = svc;
  inst-&amp;gt;current_char = -1;
  bool found = false;
  for (int i = 0; i &amp;lt; inst-&amp;gt;common-&amp;gt;init-&amp;gt;nuuids; i++)
  {
    if (inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].service != inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[svc].name)
      continue;
    inst-&amp;gt;char_ehandles[i] = inst-&amp;gt;serv_ehandles[svc];
    found =true;
  }
  if (!found){
    return false;
  }
  
  start_char_discovery(inst-&amp;gt;conn, inst-&amp;gt;serv_handles[svc] + 1, inst-&amp;gt;serv_ehandles[svc]);
  return true;
}

bool generic_on_svc_disc_evt(driver_inst_t *inst, const struct bt_gatt_attr *attr)
{
   
  if (!attr)
  {
  
    for (int i = 0; i &amp;lt; inst-&amp;gt;common-&amp;gt;init-&amp;gt;nuuids; i++)
    {
      
      if (inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].name == inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].service)
      {
        if (scan_chars(inst, i))
        {
          return false;
        }  
      }
    }
    return false;
  }
  //printk(&amp;quot;sdfghjkl\n&amp;quot;);
  char str[BT_UUID_STR_LEN];
	struct bt_gatt_service_val * gatt_service = attr-&amp;gt;user_data;
	bt_uuid_to_str(gatt_service-&amp;gt;uuid, str, sizeof(str));
  u_t* my_uuid = (u_t*)gatt_service-&amp;gt;uuid;
  struct bt_uuid_16 uuid = my_uuid-&amp;gt;u16;
  //printk(&amp;quot;Service: %s\n&amp;quot;, str);

  if (inst-&amp;gt;current_svc &amp;gt;= 0)
  {
    if (attr-&amp;gt;handle &amp;lt;= inst-&amp;gt;serv_ehandles[inst-&amp;gt;current_svc])
    {
      inst-&amp;gt;serv_ehandles[inst-&amp;gt;current_svc] = attr-&amp;gt;handle - 1;
    }
  }


  for (int i = 0; i &amp;lt; inst-&amp;gt;common-&amp;gt;init-&amp;gt;nuuids; i++)
  {
    if (inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].name != inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].service)
      continue;
    if (compare_uuids(my_uuid, &amp;amp;inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].uuid, inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].mask))
    {
      inst-&amp;gt;serv_handles[i] = attr-&amp;gt;handle;
      inst-&amp;gt;current_svc = i;
      return true;
    }
  }
  return false;
}

static void do_connect(driver_inst_t *inst)
{
  //printk(&amp;quot;Discovery completed\r\n&amp;quot;);
  inst-&amp;gt;current_cccd = -1;
  if (inst-&amp;gt;common-&amp;gt;init-&amp;gt;presub_func)
    inst-&amp;gt;common-&amp;gt;init-&amp;gt;presub_func(inst);
  generic_enable_notif(inst);
}

bool generic_on_cccd_disc_evt(driver_inst_t *inst, const struct bt_gatt_attr *attr)
{

  if (!attr)
  {
    for (int i = inst-&amp;gt;current_char + 1; i &amp;lt; inst-&amp;gt;common-&amp;gt;init-&amp;gt;nuuids; i++)
    {
      if (inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].name == inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].service)
        continue;
      if (!inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].cccd)
        continue;
      inst-&amp;gt;current_char = i;
      start_cccd_discovery(inst, inst-&amp;gt;char_handles[i] + 1, inst-&amp;gt;char_ehandles[i]);
      return false;
    }
    //printk(&amp;quot;All cccd&amp;#39;s discovered..........................................................\n&amp;quot;);
    do_connect(inst);
    return false;
  }
  inst-&amp;gt;cccd_handles[inst-&amp;gt;current_char] = attr-&amp;gt;handle;
  return true;
}

static void print_chrc_props(uint8_t properties)
{
	if (properties &amp;amp; BT_GATT_CHRC_BROADCAST) {
		//printk(&amp;quot;Properties:  BT_GATT_CHRC_BROADCAST\n&amp;quot;);
	}

	if (properties &amp;amp; BT_GATT_CHRC_READ) {
		//printk(&amp;quot;Properties: BT_GATT_CHRC_READ\n&amp;quot;);
	}

	if (properties &amp;amp; BT_GATT_CHRC_WRITE) {
		//printk(&amp;quot;Properties: BT_GATT_CHRC_WRITE\n&amp;quot;);
	}

	if (properties &amp;amp; BT_GATT_CHRC_WRITE_WITHOUT_RESP) {
		//printk(&amp;quot;Properties: BT_GATT_CHRC_WRITE_WITHOUT_RESP\n&amp;quot;);
	}

	if (properties &amp;amp; BT_GATT_CHRC_NOTIFY) {
		//printk(&amp;quot;Properties: BT_GATT_CHRC_NOTIFY\n&amp;quot;);
	}

	if (properties &amp;amp; BT_GATT_CHRC_INDICATE) {
		//printk(&amp;quot;Properties: BT_GATT_CHRC_INDICATE\n&amp;quot;);
	}

	if (properties &amp;amp; BT_GATT_CHRC_AUTH) {
		//printk(&amp;quot;Properties: BT_GATT_CHRC_AUTH\n&amp;quot;);
	}

	if (properties &amp;amp; BT_GATT_CHRC_EXT_PROP) {
		//printk(&amp;quot;Properties: BT_GATT_CHRC_EXT_PROP\n&amp;quot;);
	}
}
bool generic_on_char_disc_evt(driver_inst_t *inst, const struct bt_gatt_attr *attr)
{
  if (!attr)
  { 
    //printk(&amp;quot;End of char discovery\n&amp;quot;);
    for (int i = inst-&amp;gt;current_svc + 1; i &amp;lt; inst-&amp;gt;common-&amp;gt;init-&amp;gt;nuuids; i++)
    {
      if (inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].name == inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].service)
      {
        scan_chars(inst, i);
        return false;
      }
    }
    //printk(&amp;quot;All chars discovered\n&amp;quot;);

    for (int i = 0; i &amp;lt; inst-&amp;gt;common-&amp;gt;init-&amp;gt;nuuids; i++)
    {
    
      if (inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].name == inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].service){
        continue;
      }
      if (!inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].cccd){
        continue;
      }
       
      inst-&amp;gt;current_char = i;      
      start_cccd_discovery(inst, inst-&amp;gt;char_handles[i] + 1, inst-&amp;gt;char_ehandles[i]);
      
      return false;
    }
    //printk(&amp;quot;All cccd&amp;#39;s discovered\n&amp;quot;);
    do_connect(inst);

    return false;
  }
  char str[BT_UUID_STR_LEN];
  struct bt_gatt_chrc *value = (struct bt_gatt_chrc *)attr-&amp;gt;user_data;
  bt_uuid_to_str(value-&amp;gt;uuid, str, sizeof(str));
  u_t *uuid = (u_t *)value-&amp;gt;uuid;

  print_chrc_props(value-&amp;gt;properties);

  if (inst-&amp;gt;current_char &amp;gt;= 0)
  {
    if (attr-&amp;gt;handle &amp;lt;= inst-&amp;gt;char_ehandles[inst-&amp;gt;current_char])
    {
    	inst-&amp;gt;char_ehandles[inst-&amp;gt;current_char] = attr-&amp;gt;handle - 1;
    }
  }

  for (int i = 0; i &amp;lt; inst-&amp;gt;common-&amp;gt;init-&amp;gt;nuuids; i++)
  {
    if (compare_uuids(uuid, &amp;amp;inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].uuid, inst-&amp;gt;common-&amp;gt;init-&amp;gt;uuids[i].mask))
    {
      inst-&amp;gt;char_handles[i] = value-&amp;gt;value_handle;
      inst-&amp;gt;current_char = i;
      return true;
    }
  }
  return false;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;This is the main codes used my project. Please give any corrections.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Simultanious data reading from connected devices to central.</title><link>https://devzone.nordicsemi.com/thread/411012?ContentTypeID=1</link><pubDate>Tue, 21 Feb 2023 07:45:09 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:caf2710a-86fb-4c7c-bec9-b8aa68b76640</guid><dc:creator>Einar Thorsrud</dc:creator><description>&lt;p&gt;You can refer to the &lt;a href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.2.0/zephyr/samples/bluetooth/central_multilink/README.html"&gt;multilink central sample&lt;/a&gt; for how to connect to multiple peripherals at once. This does not actually read any data or do anything else, but for that you esentially&amp;nbsp;just iterate/loop through all connected devices and read them one by one (all&amp;nbsp;connection related API calls&amp;nbsp;takes a&amp;nbsp;bt_conn parameter that is a handle tot hat specific connection).&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Simultanious data reading from connected devices to central.</title><link>https://devzone.nordicsemi.com/thread/410994?ContentTypeID=1</link><pubDate>Tue, 21 Feb 2023 04:38:03 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b1951e15-c784-4667-8689-e5e5c2c17aa1</guid><dc:creator>ATHULYA SHAJI</dc:creator><description>&lt;p&gt;Hi&lt;/p&gt;
&lt;p&gt;Thank you for your response. Any sample code formultiple data reading?&amp;nbsp; Here I give scaning and connection parameters.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;struct bt_le_scan_param scan_param = {
      .type = BT_LE_SCAN_TYPE_ACTIVE,
      .options = BT_HCI_LE_SCAN_FILTER_DUP_DISABLE,
      .interval = SCAN_INTERVAL,
      .window = SCAN_WINDOW,
  };
  
  struct bt_conn_le_create_param create_param = {
		.options = BT_CONN_LE_OPT_NONE,
		.interval = INIT_INTERVAL,
		.window = INIT_WINDOW,
		.interval_coded = 0,
		.window_coded = 0,
		.timeout = 0,
	};
	struct bt_le_conn_param conn_param = {
		.interval_min = CONN_INTERVAL,
		.interval_max = CONN_INTERVAL,
		.latency = CONN_LATENCY,
		.timeout = CONN_TIMEOUT,
	};&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Simultanious data reading from connected devices to central.</title><link>https://devzone.nordicsemi.com/thread/410900?ContentTypeID=1</link><pubDate>Mon, 20 Feb 2023 13:21:46 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:9ce06fe2-0137-4252-abbd-4bd854d05ea9</guid><dc:creator>Einar Thorsrud</dc:creator><description>&lt;p&gt;Hi Athulya,&lt;/p&gt;
&lt;p&gt;You will not be able to read data at the exact same time, but it is for instance possible for a central to be connected to multiple peripheral devices at the same time, and read a characteristic from each, one after another (within the limitations of having to wait for a connection event on each of the links). In practice, you would just read from each one, and the stack would handle the details for you.&lt;/p&gt;
&lt;p&gt;Perhaps you can elaborate a bit on what you are doing, what you want to do, and in what way you are having problems with it?&lt;/p&gt;
&lt;p&gt;Einar&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>