This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Handling multiple characteristics

Hi, I am developing a central application that should get data from a single or even multiple primary services with multiple characteristics in Zephyr.  I am using the central_ht sample as a starting point.

static void connected(struct bt_conn *conn, uint8_t conn_err)
{
	char addr[BT_ADDR_LE_STR_LEN];
	int err;

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	if (conn_err) {
		printk("Failed to connect to %s (%u)\n", addr, conn_err);

		bt_conn_unref(default_conn);
		default_conn = NULL;

		start_scan();
		return;
	}

	if (conn != default_conn) {
		return;
	}

	printk("Connected: %s\n", addr);

	if (conn == default_conn) {
		memcpy(&uuid, BT_UUID_TEMP_128, sizeof(uuid));
		discover_params.uuid = &uuid.uuid;
		discover_params.func = discover_func;
		discover_params.start_handle = 0x0001;
		discover_params.end_handle = 0xffff;
		discover_params.type = BT_GATT_DISCOVER_PRIMARY;

		err = bt_gatt_discover(default_conn, &discover_params);
		if (err) {
			printk("Discover failed(err %d)\n", err);
			return;
		}
	}

After a connection has been established, the above code will discover the primary service and call the discover function below.

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_TEMP_128)) {
			memcpy(&uuid, BT_UUID_TEMP_SENS_128, 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_TEMP_SENS_128)) {
			memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid));
			discover_params.uuid = &uuid.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_INDICATE;
			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] to handle No.:%u\n",attr->handle);
			}
			
			return BT_GATT_ITER_STOP;
	}

	return BT_GATT_ITER_STOP;
		
}

Here I filter for a specific Characteristic.  I am not sure how to subscribe to all the characteristics and then pass each characteristic's data to their respective notify function if that is even possible.  Is this the right way to approach multiple characteristics in a single service or even multiple services with multiple characteristics?  Is there a different approach I can look at?

Your help would be highly appreciated.

Related