How to enable multiple notifications in central side

Hi,

I am currently working on creating a BLE central using nRF52840 with SDKv2.0.0.

For this, I am started with the example code ble_central_hr. I have set up a peripheral on nRF52832 and it is possible to receive the data.

To receive multiple notifications in a single service, I have set up the peripheral, and multiple notifications are available while testing this with nRF connect mobile app.

Now, I want to receive these notifications in central side. While using discover function it is possible to find out the attributes, but notifications comes out for a single characteristics only.

How can I set up these notifications for multiple characteristics in a single service

Parents
  • Hello,

    Now, I want to receive these notifications in central side. While using discover function it is possible to find out the attributes, but notifications comes out for a single characteristics only.

    How can I set up these notifications for multiple characteristics in a single service

    How have you defined these custom characteristics - have you added CCCD for them?
    You can view how to add CCCD (notification) to a characteristic in this custom service and characteristic tutorial. Particularly, in the mention of the my_service.c file.

    Best regards,
    Karl

  • For me, peripheral side is Ok. It is possible to create services and characteristics. When this peripheral is tested with nRF connect app, all services are listed and it is possible me to receive notifications (A sample image is added)

      

    But I need to implement this feature in my central(receiving multiple notifications) How can I figure out these in central (in my case nRF52840dk?

  • Thanks for sharing the link. But I have already got notification for a Service .I don't know whether it is possible to read notifications from multiple characteristics in a single service. I am sharing my Discover function and present output. Also, I am adding my expected output. Please let me know if my approach is wrong.

    static uint8_t discover_func(struct bt_conn *conn,
    			     const struct bt_gatt_attr *attr,
    			     struct bt_gatt_discover_params *params)
    {
    	int err;
    
    	if (!attr) {
    		printk("Discover complete\n");
    		(void)memset(params, 0, sizeof(*params));
    		return BT_GATT_ITER_STOP;
    	}
    
    	printk("[HRS ATTRIBUTE] handle %u\n", attr->handle);
    	if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_HRS)) {
            
    		memcpy(&uuid2, BT_UUID_HRS_BODY_SENSOR, sizeof(uuid2));
    		discover_params2.uuid = &uuid2.uuid;
    		discover_params2.start_handle = attr->handle + 1;
    		discover_params2.func=disco_func;
    		discover_params2.type = BT_GATT_DISCOVER_CHARACTERISTIC;
    		
    		err = bt_gatt_discover(conn, &discover_params2);
    		if (err) {
    			printk("Discover failed (err %d)\n", err);
    		}
    
    		memcpy(&uuid, BT_UUID_HRS_MEASUREMENT, sizeof(uuid));
    		discover_params.uuid = &uuid.uuid;
    		discover_params.start_handle = attr->handle + 1;
    		discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
    
    		err = bt_gatt_discover(conn, &discover_params);
    		if (err) {
    			printk("Discover failed (err %d)\n", err);
    		}
    	}
    	else if ((!bt_uuid_cmp(discover_params.uuid,
    				BT_UUID_HRS_MEASUREMENT)) &&
    				(!bt_uuid_cmp(discover_params2.uuid,BT_UUID_HRS_BODY_SENSOR)))
    	{
            memcpy(&uuid2, BT_UUID_GATT_CCC, sizeof(uuid2));
    		discover_params2.uuid = &uuid2.uuid;
    		discover_params2.func=disco_func;
    		discover_params2.start_handle = attr->handle + 2;
    		discover_params2.type = BT_GATT_DISCOVER_DESCRIPTOR;
    		subscribe_params2.value_handle = bt_gatt_attr_value_handle(attr);
    
    		err = bt_gatt_discover(conn, &discover_params2);
    		if (err) {
    			printk("Discover failed (err %d)\n", err);
    		}
    
    		memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid));
    		discover_params.uuid = &uuid.uuid;
    		//discover_params.func=hrs_read_func;
    		discover_params.start_handle = attr->handle + 2;
    		discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
    		subscribe_params.value_handle = bt_gatt_attr_value_handle(attr);
    
    		err = bt_gatt_discover(conn, &discover_params);
    		if (err) {
    			printk("Discover failed (err %d)\n", err);
    		}
    	}		
    	else {
    		if(notify_check_flag)
    	    {
    			notify_check_flag=false;
    			subscribe_params.notify = notify_func;
    			subscribe_params.value = BT_GATT_CCC_NOTIFY;
    			subscribe_params.ccc_handle = attr->handle;
    
    
    
    			err = bt_gatt_subscribe(conn, &subscribe_params);
    			if (err && err != -EALREADY) {
    				printk("Subscribe failed (err %d)\n", err);
    			} else {
    				printk("[HRS SUBSCRIBED]\n");
    			}
    			return BT_GATT_ITER_CONTINUE;
    		}
    		else
    		{
    		
    			notify_check_flag=true;
    			subscribe_params2.notify = notify_func2;
    			subscribe_params2.value = BT_GATT_CCC_NOTIFY;
    			subscribe_params2.ccc_handle = attr->handle;
    
    			err = bt_gatt_subscribe(conn, &subscribe_params2);
    			if (err && err != -EALREADY) {
    				printk("Subscribe failed (err %d)\n", err);
    			} else {
    				printk("[HRS value SUBSCRIBED]\n");
    			}
    			return BT_GATT_ITER_CONTINUE;
    	    }
    	}
    
    	return BT_GATT_ITER_STOP;
    }

    The discover function:

    My current output is as follows;

    *** Booting Zephyr OS build v3.0.99-ncs1 ***
    ZBeats Gateway Code[Bluetooth initialized
    Scanning successfully started
    [DEVICE]: 5D:82:EA:07:85:9F (random), AD evt type 3, AD data len 31, RSSI -78
    [DEVICE]: 10:5A:17:DE:2D:25 (public), AD evt type 0, AD data len 28, RSSI -65
    [AD]: 1 data_len 1
    [AD]: 2 data_len 2
    [AD]: 22 data_len 19
    [DEVICE]: 10:5A:17:DE:2D:25 (public), AD evt type 4, AD data len 30, RSSI -65
    [DEVICE]: F6:CB:A8:66:C1:51 (random), AD evt type 0, AD data len 11, RSSI -32
    [AD]: 1 data_len 1
    [AD]: 3 data_len 6
    Connected: F6:CB:A8:66:C1:51 (random)
    Heart rate service found
    Battery service found
    [HRS ATTRIBUTE] handle 25
    Heart rate Measurement Characteristics found
    [BAS ATTRIBUTE] handle 16
    BATTERY level characteristics found
    [HRS ATTRIBUTE] handle 26
    Current body Handle is 27
    Current measurement Handle is 27
    [BAS ATTRIBUTE] handle 17
    [HRS ATTRIBUTE] handle 28
    Current Handle is 28
    [HRS SUBSCRIBED]
    [HRS ATTRIBUTE] handle 31
    Current Handle 2 is 31

    executing else part[HRS value SUBSCRIBED]
    [BAS ATTRIBUTE] handle 19
    [BAS SUBSCRIBED]
    Discover complete

    PATCH STATUS:{"sn":12,"tm":45}
    PATCH DATA:{"sn":12,"tm":45}
    Battery percentage :9

    PATCH STATUS:{"sn":12,"tm":45}
    PATCH DATA:{"sn":12,"tm":45}
    Battery percentage :8

    However I expect to get the following output;

    *** Booting Zephyr OS build v3.0.99-ncs1 ***
    ZBeats Gateway Code[Bluetooth initialized
    Scanning successfully started
    [DEVICE]: 5D:82:EA:07:85:9F (random), AD evt type 3, AD data len 31, RSSI -78
    [DEVICE]: 10:5A:17:DE:2D:25 (public), AD evt type 0, AD data len 28, RSSI -65
    [AD]: 1 data_len 1
    [AD]: 2 data_len 2
    [AD]: 22 data_len 19
    [DEVICE]: 10:5A:17:DE:2D:25 (public), AD evt type 4, AD data len 30, RSSI -65
    [DEVICE]: F6:CB:A8:66:C1:51 (random), AD evt type 0, AD data len 11, RSSI -32
    [AD]: 1 data_len 1
    [AD]: 3 data_len 6
    Connected: F6:CB:A8:66:C1:51 (random)
    Heart rate service found
    Battery service found
    [HRS ATTRIBUTE] handle 25
    Heart rate Measurement Characteristics found
    [BAS ATTRIBUTE] handle 16
    BATTERY level characteristics found
    [HRS ATTRIBUTE] handle 26
    Current body Handle is 27
    Current measurement Handle is 27
    [BAS ATTRIBUTE] handle 17
    [HRS ATTRIBUTE] handle 28
    Current Handle is 28
    [HRS SUBSCRIBED]
    [HRS ATTRIBUTE] handle 31
    Current Handle 2 is 31

    executing else part[HRS value SUBSCRIBED]
    [BAS ATTRIBUTE] handle 19
    [BAS SUBSCRIBED]
    Discover complete

    PATCH STATUS:{"time":123456,"status":"on"}
    PATCH DATA:{"sn":12,"tm":45}
    Battery percentage :9

    PATCH STATUS:{"time":123456,"status":"on"}
    PATCH DATA:{"sn":12,"tm":45}
    Battery percentage :8

  • Hello,

    Vishnu Vijayan said:
    I don't know whether it is possible to read notifications from multiple characteristics in a single service.

    You can enable notifications for multiple characteristics within the same service, yes, no problem :) 

    From your included log output it seems to me that you successfully subscribe to the HRS and BAT characteristic, but you only receive notifications about the battery percentage in this log. How often does the HRS characteristic issue a notification? Have you verified that the peripheral is sending notifications on this characteristic?

    Best regards,
    Karl

  • Peripheral is sending notifications correctly, Please find the previous image I have attached. It is nRF connect app which receive notifications from these characteristics. Also the Battery service can receive notifications simultaneously.

    I have problem in my central side to receive these notifications simultaneously

  • Vishnu Vijayan said:
    It is nRF connect app which receive notifications from these characteristics. Also the Battery service can receive notifications simultaneously.

    What do you mean by this? I do not understand what you mean when you say that the battery service can receive notifications simultaneously.

    Best regards,
    Karl

  • Simply means it is possible for me to receive notification from battery service and heart rate service simultaneously. (That is in the case of nRF connect app;see the picture I have attached.

    /resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1660905676945v1.jpeg)

Reply Children
  • Any update on this? I am struggling with a similar issue: trying to connect to multiple characteristics of the same service

  • Hello again,

    Thank you for your patience with this.

    Vishnu Vijayan said:
    Simply means it is possible for me to receive notification from battery service and heart rate service simultaneously. (That is in the case of nRF connect app;see the picture I have attached.

    To receive notifications from the heartrate and bas characteristics simultaneously you will just need to add them to your discovery function (to look for them specifically), and then to call their respective subscribe function if they are found.
    You could essentially merge the main.c from central_bas and peripheral_hrs and create two bt_gatt_dm_cb instances, and perform both in series in the gatt_discovery function - this would subscribe you to both the battery level and heart rate measurement, at the convenience cost of having to perform discovery twice.

    The best practice here, If you instead have multiple services (could also be custom), would however be to instead iteratively search through all services offered by the peripheral device by using the bt_gatt_dm_start with NULL passed as the svc_uuid argument.
    As described in the documentation, this will discover each service after the other. Once a service is found you will enter the registered callback, in which you can subscribe to the notifications for that service's characteristics, or you can use bt_gatt_dm_continue to continue the discovery for the next service in case the found service does not match the uuid you were looking for.
    This way, you can look through the entire list of available services and enable notifications if applicable.

    This is also the case for you, jpittevils - you can follow this same approach for your custom characteristics as well.

    Best regards,
    Karl

Related