Private GATT NOTIFY

I have defined a private GATT Service with several cahractersitics.  I have defined a 128bit UUID::

static struct bt_uuid_128 data_uuid = BT_UUID_INIT_128(
	BT_UUID_128_ENCODE(0xE700AA94, 0xB681, 0xFF0C, 0xAC74, 0x8C4A1EBDA6805));

Then I define the charactersitic:

	BT_GATT_CHARACTERISTIC(&data_uuid.uuid,
		BT_GATT_CHRC_NOTIFY, 
		BT_GATT_CHRC_NOTIFY, NULL, NULL, NULL),
	BT_GATT_CCC(data_ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),

In my NOTIFY callback:

static void data_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
{
	privateAttr = attr;
	data_notif_enabled = (value == BT_GATT_CCC_NOTIFY);
	LOG_INF("Log notifications %s", data_notif_enabled ? "enabled" : "disabled");
}

Then I've defined a notify function where i invoke:

bt_gatt_notify_uuid(NULL, &data_uuid.uuid, privateAttr, &myData, sizeof(myData));

But my NOTIFY characteristic isn't updating.  I have followed the exact same pattern as a I did with a public GATT that works perfectly.

NOTE:

One thing I am not sure of is about how I'm getting the attr parameter from the function call i'm using to notify;

static inline int bt_gatt_notify_uuid(struct bt_conn *conn,
				      const struct bt_uuid *uuid,
				      const struct bt_gatt_attr *attr,
				      const void *data, uint16_t len)
{
	struct bt_gatt_notify_params params;

	memset(&params, 0, sizeof(params));

	params.uuid = uuid;
	params.attr = attr;
	params.data = data;
	params.len = len;
#if defined(CONFIG_BT_EATT)
	params.chan_opt = BT_ATT_CHAN_OPT_NONE;
#endif /* CONFIG_BT_EATT */

	return bt_gatt_notify_cb(conn, &params);
}

Can anyone please help me. This code has to go out to the custimer tomorrow.

Thanks, Drew

  • Hello Drew,

    Could you share what return value you receive from your call to bt_gatt_notify_uuid?

    Thanks,

    Helmut Lord

  • As coded above the bt_gatt_notify_uuid() function returns "-128".  I also receive a LOG_WRN message "Link is not encrypted".

    As A workaround, this is how I've had to define the characteristic:

        BT_GATT_CHARACTERISTIC(&data_uuid.uuid,
            BT_GATT_CHRC_NOTIFY | BT_GATT_CHRC_READ,
            BT_GATT_PERM_READ, read_data, NULL, NULL),
    	BT_GATT_CCC(data_ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
    

    Then I declare a bt_gatt_attr in global scope:

    struct bt_gatt_attr *privateAttr;

    And assign it to the attr passed into the read callback:

    static ssize_t read_data(
    
        struct bt_conn *conn,
        const struct bt_gatt_attr *attr,
        void *buf, uint16_t len, uint16_t offset)
    {
    
    	privateAttr = attr; // TODO: Acquire attribute
    		
    	uint8_t logData[10];
    
    	getLogData((uint8_t*)&logData);
    
        return bt_gatt_attr_read(conn, attr, buf, len, offset, &logData, sizeof(logData));
    }

    And that is used in my bt_gatt_notify_uuid() call:

    uint8_t data_notify(void) 
    {
    	//LOG_INF("Data Notification");
    
    	int err;
    
    	uint8_t logData[10];
    
    	getLogData((uint8_t*)&logData);
    
    	err = bt_gatt_notify_uuid(NULL, &data_uuid.uuid, privateAttr, &logData, sizeof(logData));
    	if(err) {
    
    		LOG_DBG("Data Notify Error = %d", err);
    		return err;
    	}
    
    	return 1;
    }

    This works but it is a bit of a hack as our customer only required a NOTIFY property on this characteristic.

    Again, I believe the issue might be in how I am acquiring the "attr" parameter from the bt_gatt_notify_uuid() call.

    Any suggestions would be appreciated.

    -Drew

  • Yes!! This allows me to define an attrs struct:

    static struct bt_gatt_attr svc_attrs[] = {{&data_uuid.uuid}};
    static struct bt_gatt_service logAttrs;

    Then in main:

    logAttrs = (struct bt_gatt_service)BT_GATT_SERVICE(svc_attrs);

    In my notify function:

    err = bt_gatt_notify_uuid(NULL, &data_uuid.uuid, logAttrs.attrs, &logData, sizeof(logData));

    And I'm able to eliminate the write property from my characteristic:

    	BT_GATT_CHARACTERISTIC(&data_uuid.uuid,
    		BT_GATT_CHRC_NOTIFY, 
    		BT_GATT_PERM_READ, NULL, NULL, NULL),
    	BT_GATT_CCC(data_ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
    

    Thank you, Amanda for your guidance. If you see any glaring errors in my implementation above, I welcome your suggestions. Otherwise you may consider this matter solved.

    Drew

Related