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 Reply Children
  • 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. 
Related