hrs example with btuuid128

The zephyr peripheral hr example us altered create a custom GATT service with a 128 bit BT uuid instead of a 16 bit bt number. I tried the following which does not trigger the notify event:

On the peripheral role, I changed advertising data and service definitions. I won't bother you with my code, it works in nrf52 connectivity.

#define uuid_ppg_service_val BT_UUID_128_ENCODE(0x20000001, 0xA000, 0xB000, 0xC000, 0xC00000000001)
#define BT_UUID_PPGS BT_UUID_DECLARE_128(uuid_ppg_service_val)
#define BT_UUID_PPGS_MEASUREMENT BT_UUID_DECLARE_128(BT_UUID_128_ENCODE(0x10000001, 0xA000, 0xB000, 0xC000, 0xC00000000002))

BT_GATT_SERVICE_DEFINE(ppg_svc,
	BT_GATT_PRIMARY_SERVICE(BT_UUID_PPGS),	
		BT_GATT_CHARACTERISTIC(BT_UUID_PPGS_MEASUREMENT,
					BT_GATT_CHRC_NOTIFY, 
					BT_GATT_PERM_NONE, NULL, NULL, NULL),
			BT_GATT_CCC(vnd_ccc_cfg_changed,
					BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),				
);

static const struct bt_data ad[] = {
	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
	BT_DATA_BYTES(BT_DATA_UUID16_ALL,
			  //BT_UUID_16_ENCODE(BT_UUID_HRS_VAL),
		      	BT_UUID_16_ENCODE(BT_UUID_BAS_VAL),
			  ),
	BT_DATA_BYTES(BT_DATA_UUID128_ALL, uuid_ppg_service_val),
};

On the central role, I made these modifications:

static void connected(struct bt_conn *conn, uint8_t conn_err)
{
    // ... 
    if (conn == default_conn) {
        memcpy(&uuid128, BT_UUID_PPGS, sizeof(uuid128));				
		discover_params.uuid = &uuid128.uuid;
	//...
}

static bool eir_found(struct bt_data *data, void *user_data)
{
	bt_addr_le_t *addr = user_data;
	int i;
	int err;

	printk("[AD]: %u data_len %u\n", data->type, data->data_len);
	struct bt_le_conn_param *param;
	param = BT_LE_CONN_PARAM_DEFAULT;

	switch (data->type) {
		case BT_DATA_UUID128_SOME:
			printk("128bit type some");
			break;
		case BT_DATA_UUID128_ALL:
			if (data->data_len % BT_UUID_SIZE_128 != 0U) {
				printk("AD malformed\n");
				return true;
			}
			for(i = 0; i < data->data_len; i+= BT_UUID_SIZE_128) {
				
				printk("128bit type all");
				struct bt_uuid *uuid128;
				uint8_t btadvData[16];
				memcpy(btadvData, data->data, 16);
				uuid128 = (struct bt_uuid *)btadvData;
				if(bt_uuid_cmp(uuid128, BT_UUID_PPGS_MEASUREMENT)) {
					printk("uuid128 == PPGID\n");				
					err = bt_le_scan_stop();
					if(err) {
						printk("Stop LE scan failed (err %d)\n", err);					
					}
					printk("make connection");
					err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
								param, &default_conn);
					if (err) {
						printk("Create conn failed (err %d)\n", err);					
					}		
					return false;			
				}
			}
			break;
		}
	return true;
}

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("[ATTRIBUTE] handle %u\n", attr->handle);

	if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_PPGS)) {
		memcpy(&uuid128, BT_UUID_PPGS_MEASUREMENT, sizeof(uuid128));
		discover_params.uuid = &uuid128.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_PPGS_MEASUREMENT)) {
		memcpy(&uuid16, BT_UUID_GATT_CCC, sizeof(uuid16));
		discover_params.uuid = &uuid16.uuid;
		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 {
		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("[SUBSCRIBED]\n");
		}

		return BT_GATT_ITER_STOP;
	}

	return BT_GATT_ITER_STOP;
}

Central connects but notifications do not work. When I change back to BT_UUID_HRS value, notifications are received.

Parents
  • Hi Boris, 

    I would suggest to use a nRF Sniffer to track what happen over the air so we can have better understanding on what the central and peripheral is doing. 

    Have you checked if the central managed to do service discovery and the discover_func() callback is called ? And how many times it has been called ? 

    I would suggest to have a look into our central_uart (and peripheral_uart) sample. The examples show how to use a 128 bits UUID proprietary service/characteristic. 

  • I knew you would come up with nordic uart, but that example uses a lot of nordic libraries, I just want to use a custom uuid in the zephyr example. discover_func is called, once. I'll try the sniffer.

  • Hi Boris, 


    If you don't want to use Nordic library, you still can have a look at the gatt_dm.c and see how we used 

    Zephyr's bt_gatt_discover() library inside that. 
    From what I can see it's not much different from the central_hr example. What you need to check is to see when discover_func() returned if it managed to find the NUS service or not (please try to test your application using NUS UUID first). If not then you would need to check what's the difference in central_nus example that it managed to discover the service. Make sure you declare the exact same UUID on both the central and peripheral. 
Reply
  • Hi Boris, 


    If you don't want to use Nordic library, you still can have a look at the gatt_dm.c and see how we used 

    Zephyr's bt_gatt_discover() library inside that. 
    From what I can see it's not much different from the central_hr example. What you need to check is to see when discover_func() returned if it managed to find the NUS service or not (please try to test your application using NUS UUID first). If not then you would need to check what's the difference in central_nus example that it managed to discover the service. Make sure you declare the exact same UUID on both the central and peripheral. 
Children
No Data
Related