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
  • Sorry I made an mistake, the discover_func callback needs an 16bit uuid for BT_UUID_GATT_CCC. I changed that now it works. Resides one more question:

    Why does eir_found loops through the data in the hr_central example. bt_data_parse function explanations says: "Callback function which will be called for each element that's found in the data. The callback should return true to continue parsing, or false to stop parsing.".

  • Hi Boris, 
    I'm sorry for late reply. You are right on the fact that the callback will be called for each element found in the advertising data.  The BT_DATA_UUID16_ALL and BT_DATA_UUID16_SOME are considered a element but as the name suggest (all or some), they may contain multiple UUIDs inside.

    This is why we need to go through it to find if the HRS UUID is inside. 

Reply Children
No Data
Related