can't receive notifications from my BLE peripheral on my BLE central

Hi,

i've been working on a ble central that's supposed to read tempeture value from a ble peripheral that i made ( i can read that value and see it being updated from the nRF connect application).

But when i try to do the same with the ble central (that is based on the Central_hr sample) this is the results i get :

i tried fixing it but i can't seem to find why i don't receive any data

  • Hi

    It's impossible to say from this log snippet what's going wrong, as the prints doesn't tell me anything except the dscovery procedure and subscription is being done... My assumption is that your central device doesn't read and print the temperature values to the serial interface, but I don't know what you're doing on your central side so hard to say what exact functions are missing.

    If you're not sure I'd recommend checking out the BLE fundamentals course on the DevAcademy, and specifically the lessons 3 and 4 that covers BLE connections and data exchanges: https://academy.nordicsemi.com/courses/bluetooth-low-energy-fundamentals/lessons/lesson-1-bluetooth-low-energy-introduction/

    Best regards,

    Simon

  • Hi Simon,

    in fact i've followed those courses and my application now connects to the peripheral and is able to read the UUID but this is as far as i could go,

    here's the code i used : 

    #include "ble_central_scan.h"
    
    LOG_MODULE_REGISTER(ble_central_test, LOG_LEVEL_INF);
    
    struct bt_conn *default_conn;
    char ble_periphs[3][18]={"EE:1E:F3:8D:55:B9","",""};
    
    struct bt_uuid_16 discover_uuid = BT_UUID_INIT_16(0);
    struct bt_gatt_discover_params discover_params;
    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)
    {
    	printk("[NOTIFICATION CHECK ! ]\n");
    	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;
    }
    
    uint8_t discover_func(struct bt_conn *conn, const struct bt_gatt_attr *attr, struct bt_gatt_discover_params *params)
    {
    	printk("DISCOVER function ! \n");
    	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_TEMPSENSOR)) {
            // Set up parameters for discovering the tempeture value characteristic.
            memcpy(&discover_uuid, BT_UUID_TEMPSENSOR_READ, sizeof(discover_uuid));
            discover_params.uuid = &discover_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_TEMPSENSOR_READ)) {
            // Set up parameters for discovering the CCC descriptor.
            memcpy(&discover_uuid, BT_UUID_GATT_CCC, sizeof(discover_uuid));
            discover_params.uuid = &discover_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_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;
    }
    
    bool target_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_le_conn_param *param;
    			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_TEMPSENSOR)) {
    				continue;
    			}
    			err = bt_le_scan_stop();
    			if (err) {
    				printk("Stop LE scan failed (err %d)\n", err);
    				continue;
    			}
    
    			param = BT_LE_CONN_PARAM_DEFAULT;
    			err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
    						param, &default_conn);
    
    			if (err) {
    				printk("Create conn failed (err %d)\n", err);
    				start_scan();
    			}
    
    			return false;
    		}
    	 }
    	return true;
    }
    
    
    void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type, struct net_buf_simple *ad)
    {
    	char addr_str[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
    	printk("[DEVICE]: %s, AD evt type %u, AD data len %u, RSSI %i\n", addr_str, type, ad->len, rssi);
    	char add_test[18];
    	strncpy (add_test,addr_str,17 );
    	add_test[17]='\0';
    
    	/* connect only to devices in close proximity */
    	if (strcmp(add_test,ble_periphs[0])==0) { 
    		// if (type == BT_GAP_ADV_TYPE_ADV_IND ||
    	    // type == BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
    			
    			/* We're only interested in connectable events */
    		bt_data_parse(ad, target_found, (void *)addr);
    		
    	 }
    }
    
    void start_scan(void)
    {
    	int err;
    
    	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,
    	};
    
    	err = bt_le_scan_start(&scan_param, device_found);
    	if (err) {
    		printk("Scanning failed to start (err %d)\n", err);
    		return;
    	}
    
    	printk("Scanning successfully started\n");
    }
    
    void device_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;
    	}
    
    	printk("Connected: %s\n", addr);
    
        if (conn == default_conn) {
    		memcpy(&discover_uuid, BT_UUID_TEMPSENSOR, sizeof(discover_uuid));
    		discover_params.uuid = &discover_uuid.uuid;
    		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_PRIMARY;
    
    		err = bt_gatt_discover(default_conn, &discover_params);
    		if (err) {
    			printk("Discover failed(err %d)\n", err);
    			return;
    		}
    	}
    
    }
    
    void device_disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	if (conn != default_conn) {
    		return;
    	}
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("Disconnected: %s (reason 0x%02x)\n", addr, reason);
    
    	bt_conn_unref(default_conn);
    	default_conn = NULL;
    
    	start_scan();
    }

    The central app is acting as if i'm not receiving any data from the peripheral while i tested with "nrf connect phone app" that the peripheral is working fine.

    i hope you can help me find why i can't read the tempeture value i'm sending from my peripheral.

    thanks in advance,

    Kind regards,

  • Hi

    What is your MTU size set to in the central side here? If the notification data size is larger than the MTU size, you might not receive the notification.

    You could also try to sniff the connection to see if the packets are indeed sent from the peripheral to the central but just not printed. I also would need to see what you do after discovery on the central side, as this snippet only goes as far as to have the notifications subscribed, but I don't see where you are printing the received data on the central side. You can check out the battery level or heart rate service central samples to see how this is done in other samples.

    Best regards,

    Simon

  • Hi,

    in fact i've tested the peripheral with the mobile "nrf connect" so i know that the data is being sent.

    i based the application on the central hr sample of zephyr, so i thought this is the part where it was supposed to print the data " printk("[ATTRIBUTE] handle %u\n", attr->handle);"

    i don't really understand what you are asking for so please find attached a zip file of my application and i hope you can help locate what went wrong

    thanks in advance,

    kind regards,

    central_bleapp.zip

Related