ble notify always returns null

Trying to connect to a ble device, once I connect and discover the notification characteristic I activate it, but in the callback function it always returns null, I don't understand where I'm going wrong, the notification should send me different signals all the time.
here is my code ,
thanks for the help

/* main.c - Application main entry point */

/*
 * Copyright (c) 2020 SixOctets Systems
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stdio.h>
#include <stddef.h>
#include <errno.h>

#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/byteorder.h>

#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/bluetooth/gatt.h>
#define NAME_LEN 100

static int scan_start(void);

static struct bt_conn *default_conn;
static struct bt_uuid_16 uuid = BT_UUID_INIT_16(0);
static struct bt_gatt_discover_params discover_params;
static struct bt_gatt_subscribe_params subscribe_params;




static uint8_t notify_func(struct bt_conn *conn,
			   struct bt_gatt_subscribe_params *params,
			   const void *data, uint16_t length)
{
	// if (!data) {
	// 	printk("[UNSUBSCRIBED]\n");
	// 	params->value_handle = 0U;
	// 	return BT_GATT_ITER_STOP;
	// }

	printk("[NOTIFICATION] data %p length %u\n", data, length);

	return BT_GATT_ITER_CONTINUE;
}


static uint8_t discover_func(struct bt_conn *conn,
			     const struct bt_gatt_attr *attr,
			     struct bt_gatt_discover_params *params)
{
	struct bt_gatt_service_val *gatt_service;
	struct bt_gatt_chrc *gatt_chrc;
	struct bt_gatt_include *gatt_include;
	char str[37];

	
	if (!attr) {
			printk("Discover complete\n");
			memset(params, 0, sizeof(*params));
			return BT_GATT_ITER_STOP;
	}
	switch (params->type) {
	case BT_GATT_DISCOVER_SECONDARY:
	case BT_GATT_DISCOVER_PRIMARY:
		gatt_service = attr->user_data;
		bt_uuid_to_str(gatt_service->uuid, str, sizeof(str));
		printk("Service %s found: start handle %x, end_handle %x\n",
		       str, attr->handle, gatt_service->end_handle);
		break;

	case BT_GATT_DISCOVER_CHARACTERISTIC:
		gatt_chrc = attr->user_data;
		bt_uuid_to_str(gatt_chrc->uuid, str, sizeof(str));

		

		if (strcmp(str, "6e400002-b5a3-f393-e0a9-e50e24dcca9e")==0)
		{
			printk("Characteristic %s found: handle %x\n", str,
		       attr->handle);

			printk("Found characteristic to write\n");
			// Valore da scrivere
			uint8_t value[] = {0x01, 0x00};

			// Scrittura senza risposta
			int err = bt_gatt_write_without_response(conn, attr->handle, &value, sizeof(value), false);
			if (err) {
				printk("Failed to write value, err: %d\n", err);
			} else {
				printk("Value written successfully\n");
			}
		}else if (strcmp(str, "6e400003-b5a3-f393-e0a9-e50e24dcca9e")==0)
		{
			printk("Characteristic %s found: handle %x\n", str,
		       attr->handle);

			subscribe_params.notify = notify_func;
			subscribe_params.value = BT_GATT_CHRC_NOTIFY;
			subscribe_params.ccc_handle = attr->handle;

			int 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;
		}
		
		
		break;
	
	case BT_GATT_DISCOVER_INCLUDE:
		gatt_include = attr->user_data;
		bt_uuid_to_str(gatt_include->uuid, str, sizeof(str));
		printk("Include %s found: handle %x, start %x, end %x\n",
		       str, attr->handle, gatt_include->start_handle,
		       gatt_include->end_handle);
		break;
	default:
		bt_uuid_to_str(attr->uuid, str, sizeof(str));
		printk("Descriptor %s found: handle %x\n", str, attr->handle);
		break;
	}
	

	return BT_GATT_ITER_CONTINUE;
}




static bool data_cb(struct bt_data *data, void *user_data)
{
	char *name = user_data;
	uint8_t len;

	switch (data->type)
	{
	case BT_DATA_NAME_SHORTENED:

	case BT_DATA_NAME_COMPLETE:
		len = MIN(data->data_len, NAME_LEN - 1);
		(void)memcpy(name, data->data, len);
		name[len] = '\0';
		return false;
	default:
		return true;
	}
}

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

	printk("[AD]: %u data_len %u\n", data->type, data->data_len);

	switch (data->type)
	{
	case BT_DATA_UUID16_SOME:
	case BT_DATA_UUID16_ALL:
		if (data->data_len % sizeof(uint16_t) != 0U)
		{
			printk("AD malformed\n");
			return true;
		}

		for (i = 0; i < data->data_len; i += sizeof(uint16_t))
		{
			struct bt_uuid *uuid;
			uint16_t u16;
			int err;

			memcpy(&u16, &data->data[i], sizeof(u16));
			uuid = BT_UUID_DECLARE_16(sys_le16_to_cpu(u16));
			if (bt_uuid_cmp(uuid, BT_UUID_HTS))
			{
				continue;
			}

			err = bt_le_scan_stop();
			if (err)
			{
				printk("Stop LE scan failed (err %d)\n", err);
				continue;
			}

			err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
									BT_LE_CONN_PARAM_DEFAULT,
									&default_conn);
			if (err)
			{
				printk("Create connection failed (err %d)\n",
					   err);
				scan_start();
			}

			return false;
		}
	}

	return true;
}

static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
						 struct net_buf_simple *ad)
{
	char name[NAME_LEN];
	uint16_t data_len;

	(void)memset(name, 0, sizeof(name));
	data_len = ad->len;

	bt_data_parse(ad, data_cb, name);

	if (strcmp(name, "") != 0)
	{
		if (strstr(name, "OxySmart") != NULL){
			printk("[nome]: %s \n", name);
			char dev[BT_ADDR_LE_STR_LEN];

			bt_addr_le_to_str(addr, dev, sizeof(dev));

			printk("[DEVICE]: %s, AD evt type %u, AD data len %u, RSSI %i\n",
				   dev, type, ad->len, rssi);

			int err = bt_le_scan_stop();
			if (err)
			{
				printk("Stop LE scan failed (err %d)\n", err);
			}

			err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
									BT_LE_CONN_PARAM_DEFAULT,
									&default_conn);
			if (err)
			{
				printk("Create connection failed (err %d)\n",
					   err);
				scan_start();
			}
			/* We're only interested in connectable events */
			// bt_data_parse(ad, eir_found, (void *)addr);
		}
	}
}

static int scan_start(void)
{
	/* Use active scanning and disable duplicate filtering to handle any
	 * devices that might update their advertising data at runtime.
	 */
	struct bt_le_scan_param scan_param = {
		.type = BT_LE_SCAN_TYPE_ACTIVE,
		.options = BT_LE_SCAN_OPT_NONE,
		.interval = BT_GAP_SCAN_FAST_INTERVAL,
		.window = BT_GAP_SCAN_FAST_WINDOW,
	};

	return bt_le_scan_start(&scan_param, device_found);
}

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;

		scan_start();
		return;
	}

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

	if (conn == default_conn)
	{
		memcpy(&uuid, BT_UUID_HTS, sizeof(uuid));
		discover_params.uuid = NULL;
		discover_params.func = discover_func;
		discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
		discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
		discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
		err = bt_gatt_discover(default_conn, &discover_params);
		if (err)
		{
			printk("Discover failed(err %d)\n", err);
			return;
		}
	}
}

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

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

	printk("Disconnected: %s (reason 0x%02x)\n", addr, reason);

	if (default_conn != conn)
	{
		return;
	}

	bt_conn_unref(default_conn);
	default_conn = NULL;

	err = scan_start();
	if (err)
	{
		printk("Scanning failed to start (err %d)\n", err);
	}
}

BT_CONN_CB_DEFINE(conn_callbacks) = {
	.connected = connected,
	.disconnected = disconnected,
};

int main(void)
{
	int err;

	err = bt_enable(NULL);
	if (err)
	{
		printk("Bluetooth init failed (err %d)\n", err);
		return 0;
	}

	printk("Bluetooth initialized\n");

	err = scan_start();

	if (err)
	{
		printk("Scanning failed to start (err %d)\n", err);
		return 0;
	}

	printk("Scanning successfully started\n");
	return 0;
}

Parents
  • Hi Simone,

    Can you provide more information, as it is unclear which callback you are talking about, and what are your expectations. What do you see / get? 

    Is your project based on some example project from NCS?

    Typically, it is a good idea to start with example and build upon it.

    Can you test Peripheral Uart for example and connect using nRF connect app on mobile and see its behavior.

    And then if you modify such example, and it is not working or not showing expected output, then we can start debugging into it.

    With regards,

    Naeem

Reply
  • Hi Simone,

    Can you provide more information, as it is unclear which callback you are talking about, and what are your expectations. What do you see / get? 

    Is your project based on some example project from NCS?

    Typically, it is a good idea to start with example and build upon it.

    Can you test Peripheral Uart for example and connect using nRF connect app on mobile and see its behavior.

    And then if you modify such example, and it is not working or not showing expected output, then we can start debugging into it.

    With regards,

    Naeem

Children
No Data
Related