BT_GATT_SERVICE_DEFINE Build Error

Hi All,

I am having issue building a project where I am attempting to add a custom BLE service.

The error message is shown below along with my relevant project files. Any help would be greatly appreciated!

Error message: C:/nordic/myapps/RES-BPB/src/cab_ble_service.c:218:1: error: macro "BT_GATT_CHRC_INIT" passed 18 arguments, but takes just 3
218 | );

Custom service C File:

#include <zephyr/types.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.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>

#include "cab_ble_service.h"





LOG_MODULE_DECLARE(CAB_BLE_SERVICE);

static bool button_state;
// static struct my_lbs_cb lbs_cb;
static struct cab_cb_s cab_cb;

static bool emergency_state;
static bool indicate_enabled;

bool emergency_cb(void)
{
	return emergency_state;
}

// /* STEP 6 - Implement the write callback function of the LED characteristic */
// static ssize_t write_led(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf,
// 			 uint16_t len, uint16_t offset, uint8_t flags)
// {
// 	LOG_DBG("Attribute write, handle: %u, conn: %p", attr->handle, (void *)conn);

// 	if (len != 1U) {
// 		LOG_DBG("Write led: Incorrect data length");
// 		return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
// 	}

// 	if (offset != 0) {
// 		LOG_DBG("Write led: Incorrect data offset");
// 		return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
// 	}

// 	if (lbs_cb.led_cb) {
// 		// Read the received value
// 		uint8_t val = *((uint8_t *)buf);

// 		if (val == 0x00 || val == 0x01) {
// 			// Call the application callback function to update the LED state
// 			lbs_cb.led_cb(val ? true : false);
// 		} else {
// 			LOG_DBG("Write led: Incorrect value");
// 			return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED);
// 		}
// 	}

// 	return len;
// }

/* STEP 6 - Implement the write callback function of the LED characteristic */
// static ssize_t write_clear_ack(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf,
// 			 uint16_t len, uint16_t offset, uint8_t flags)
// {
// 	LOG_DBG("Attribute write, handle: %u, conn: %p", attr->handle, (void *)conn);

	// if (len != 1U) {
	// 	LOG_DBG("Write led: Incorrect data length");
	// 	return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
	// }

	// if (offset != 0) {
	// 	LOG_DBG("Write led: Incorrect data offset");
	// 	return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
	// }

	// if (lbs_cb.led_cb) {
	// 	// Read the received value
	// 	uint8_t val = *((uint8_t *)buf);

	// 	if (val == 0x00 || val == 0x01) {
	// 		// Call the application callback function to update the LED state
	// 		lbs_cb.led_cb(val ? true : false);
	// 	} else {
	// 		LOG_DBG("Write led: Incorrect value");
	// 		return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED);
	// 	}
	// }

// 	return len;
// }

// /* STEP 5 - Implement the read callback function of the Button characteristic */
// static ssize_t read_button(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
// 			   uint16_t len, uint16_t offset)
// {
// 	// get a pointer to button_state which is passed in the BT_GATT_CHARACTERISTIC() and stored in attr->user_data
// 	const char *value = attr->user_data;

// 	LOG_DBG("Attribute read, handle: %u, conn: %p", attr->handle, (void *)conn);

// 	if (lbs_cb.button_cb) {
// 		// Call the application callback function to update the get the current value of the button
// 		button_state = lbs_cb.button_cb();
// 		return bt_gatt_attr_read(conn, attr, buf, len, offset, value, sizeof(*value));
// 	}

// 	return 0;
// }

/* STEP 5 - Implement the read callback function of the Emergency characteristic */
static ssize_t read_emergency(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
			   uint16_t len, uint16_t offset)
{
	// get a pointer to button_state which is passed in the BT_GATT_CHARACTERISTIC() and stored in attr->user_data
	const char *value = attr->user_data;

	LOG_DBG("Attribute read, handle: %u, conn: %p", attr->handle, (void *)conn);

	if (cab_cb.emergency_cb) {
		// Call the application callback function to update the get the current value of the button
		emergency_state = cab_cb.emergency_cb;
		return bt_gatt_attr_read(conn, attr, buf, len, offset, value, sizeof(*value));
	}

	return 0;
}

/* This function is called whenever a Notification has been sent by the emergency Characteristic */
static void on_emergency_sent(struct bt_conn *conn, void *user_data)
{
	ARG_UNUSED(user_data);

    const bt_addr_le_t * addr = bt_conn_get_dst(conn);
        
	printk("Data sent to Address 0x %02X %02X %02X %02X %02X %02X \n", addr->a.val[0]
                                                                    , addr->a.val[1]
                                                                    , addr->a.val[2]
                                                                    , addr->a.val[3]
                                                                    , addr->a.val[4]
                                                                    , addr->a.val[5]);
}

static void cab_emergency_ccc_cfg_changed(const struct bt_gatt_attr *attr,
				  uint16_t value)
{
    ARG_UNUSED(attr);
    switch(value)
    {
        case BT_GATT_CCC_NOTIFY: 
            // Start sending stuff!
            break;

        case BT_GATT_CCC_INDICATE: 
            // Start sending stuff via indications
            break;

        case 0: 
            // Stop sending stuff
            break;
        
        default: 
            printk("Error, CCCD has been set to an invalid value");     
    }
}

/**
 *  @brief Characteristic and Value Declaration Macro.
 *
 *  Helper macro to declare a characteristic attribute along with its
 *  attribute value.
 *
 *  @param _uuid Characteristic attribute uuid.
 *  @param _props Characteristic attribute properties,
 *                a bitmap of ``BT_GATT_CHRC_*`` macros.
 *  @param _perm Characteristic Attribute access permissions,
 *               a bitmap of @ref bt_gatt_perm values.
 *  @param _read Characteristic Attribute read callback
 *               (@ref bt_gatt_attr_read_func_t).
 *  @param _write Characteristic Attribute write callback
 *                (@ref bt_gatt_attr_write_func_t).
 *  @param _user_data Characteristic Attribute user data.
 */

BT_GATT_SERVICE_DEFINE(
            cab_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_CAB),

		    BT_GATT_CHARACTERISTIC(BT_UUID_EMERGENCY_VAL, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
                    BT_GATT_PERM_READ, read_emergency, NULL, &emergency_state),
                    BT_GATT_CCC(cab_emergency_ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),

		    //    BT_GATT_CHARACTERISTIC(BT_UUID_CLEAR_ACK, BT_GATT_CHRC_WRITE,
			// 		      BT_GATT_PERM_WRITE, NULL, write_clear_ack, NULL),

            //    BT_GATT_CHARACTERISTIC(BT_UUID_EMERGENCY_REPORT, BT_GATT_CHRC_NOTIFY,
			// 		      BT_GATT_PERM_READ, read_button, NULL, &button_state),

		    //    BT_GATT_CHARACTERISTIC(BT_UUID_HEARTBEAT_PERIOD, BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
			// 		      BT_GATT_PERM_READ | BT_GATT_PERM_WRITE, NULL, write_led, NULL),

		    //    BT_GATT_CHARACTERISTIC(BT_UUID_HEARTBEAT, BT_GATT_CHRC_NOTIFY,
			// 		      BT_GATT_PERM_READ, read_button, NULL, &button_state),

		    //    BT_GATT_CHARACTERISTIC(BT_UUID_PUBLIC_KEY, BT_GATT_CHRC_READ,
			// 		      BT_GATT_PERM_READ, NULL, write_led, NULL),

            //    BT_GATT_CHARACTERISTIC(BT_UUID_SIGN, BT_GATT_CHRC_WRITE,
			// 		      BT_GATT_PERM_WRITE, read_button, NULL, &button_state),

		    //    BT_GATT_CHARACTERISTIC(BT_UUID_SIGN_RESULT, BT_GATT_CHRC_NOTIFY,
			// 		      BT_GATT_PERM_NONE, NULL, write_led, NULL),
);

// /* A function to register application callbacks for the LED and Button characteristics  */
// int my_lbs_init(struct my_lbs_cb *callbacks)
// {
// 	if (callbacks) {
// 		lbs_cb.led_cb = callbacks->led_cb;
// 		lbs_cb.button_cb = callbacks->button_cb;
// 	}

// 	return 0;
// }

/* A function to register application callbacks for the LED and Button characteristics  */
int Cab_Init(void)
{
	cab_cb.emergency_cb = &emergency_cb;

	return 0;
}

/* STEP 5.1 - Define the function to send indications */
void Cab_Send_Emergency_Notification(struct bt_conn *conn)
{
    /* 
    The attribute for the TX characteristic is used with bt_gatt_is_subscribed 
    to check whether notification has been enabled by the peer or not.
    Attribute table: 0 = Service, 1 = Primary service, 2 = RX, 3 = TX, 4 = CCC.
    */
    const struct bt_gatt_attr *attr = &cab_svc.attrs[2]; 

    struct bt_gatt_notify_params params = 
    {
        .uuid   = BT_UUID_EMERGENCY,
        .attr   = attr,
        .data   = &emergency_state,
        .len    = sizeof(emergency_state),
        .func   = on_emergency_sent
    };

    // Check whether notifications are enabled or not
    if(bt_gatt_is_subscribed(conn, attr, BT_GATT_CCC_NOTIFY)) 
    {
        // Send the notification
	    int err = bt_gatt_notify_cb(conn, &params);
        if(err){
            printk("Error, unable to send notification. Error %d\n", err);
        }
    }
    else
    {
        printk("Warning, notification not enabled on the selected attribute\n");
    }
}

ble service header file:

#ifndef CAB_BLE_SERVICE_H_
#define CAB_BLE_SERVICE_H_


#ifdef __cplusplus
extern "C" {
#endif

#include <zephyr/types.h>

#define BT_UUID_CAB_VAL \
	BT_UUID_128_ENCODE(0x4d2e0000, 0x3edd, 0x4a55, 0xa57a, 0x248a3c37382c)

/** @brief Emergency Characteristic UUID. */
#define BT_UUID_EMERGENCY_VAL \
	BT_UUID_128_ENCODE(0x4d2e0002, 0x3edd, 0x4a55, 0xa57a, 0x248a3c37382c)

/** @brief Clear/Ack Emergency Characteristic UUID. */
#define BT_UUID_CLEAR_ACK_VAL \
	BT_UUID_128_ENCODE(0x4d2e0003, 0x3edd, 0x4a55, 0xa57a, 0x248a3c37382c)

/** @brief Emergency Report Characteristic UUID. */
#define BT_UUID_EMERGENCY_REPORT_VAL \
	BT_UUID_128_ENCODE(0x4d2e0004, 0x3edd, 0x4a55, 0xa57a, 0x248a3c37382c)

/** @brief Heartbeat Period Characteristic UUID. */
#define BT_UUID_HEARTBEAT_PERIOD_VAL \
	BT_UUID_128_ENCODE(0x4d2e0005, 0x3edd, 0x4a55, 0xa57a, 0x248a3c37382c)

/** @brief Heartbeat Characteristic UUID. */
#define BT_UUID_HEARTBEAT_VAL \
	BT_UUID_128_ENCODE(0x4d2e0006, 0x3edd, 0x4a55, 0xa57a, 0x248a3c37382c)

/** @brief Public Key Characteristic UUID. */
#define BT_UUID_PUBLIC_KEY_VAL \
	BT_UUID_128_ENCODE(0x4d2e0007, 0x3edd, 0x4a55, 0xa57a, 0x248a3c37382c)

/** @brief Sign Characteristic UUID. */
#define BT_UUID_SIGN_VAL \
	BT_UUID_128_ENCODE(0x4d2e0008, 0x3edd, 0x4a55, 0xa57a, 0x248a3c37382c)

/** @brief Sign Result Characteristic UUID. */
#define BT_UUID_SIGN_RESULT_VAL \
	BT_UUID_128_ENCODE(0x4d2e0009, 0x3edd, 0x4a55, 0xa57a, 0x248a3c37382c)

#define BT_UUID_CAB                 BT_UUID_DECLARE_128(BT_UUID_CAB_VAL)
#define BT_UUID_EMERGENCY           BT_UUID_DECLARE_128(BT_UUID_EMERGENCY_VAL)
#define BT_UUID_CLEAR_ACK           BT_UUID_DECLARE_128(BT_UUID_CLEAR_ACK_VAL)
#define BT_UUID_EMERGENCY_REPORT    BT_UUID_DECLARE_128(BT_UUID_EMERGENCY_REPORT_VAL)
#define BT_UUID_HEARTBEAT_PERIOD    BT_UUID_DECLARE_128(BT_UUID_HEARTBEAT_PERIOD_VAL)
#define BT_UUID_HEARTBEAT           BT_UUID_DECLARE_128(BT_UUID_HEARTBEAT_VAL)
#define BT_UUID_PUBLIC_KEY          BT_UUID_DECLARE_128(BT_UUID_PUBLIC_KEY_VAL)
#define BT_UUID_SIGN                BT_UUID_DECLARE_128(BT_UUID_SIGN_VAL)
#define BT_UUID_SIGN_RESULT         BT_UUID_DECLARE_128(BT_UUID_SIGN_RESULT_VAL)

typedef bool (*emergency_cb_t)(void);

/** @brief Callback struct used by the LBS Service. */
struct cab_cb_s {
	/** LED state change callback. */
	emergency_cb_t emergency_cb;
};

int Cab_Init(void);
void Cab_Send_Emergency_Notification(struct bt_conn *conn);

#ifdef __cplusplus
}
#endif

#endif /* CAB_BLE_SERVICE_H_ */

prj.conf

#
# Copyright (c) 2018 Nordic Semiconductor
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#
CONFIG_NCS_SAMPLES_DEFAULTS=y

CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="AnyXXXX"

# Enable the LBS service
CONFIG_BT_LBS=y
CONFIG_BT_LBS_POLL_BUTTON=y
CONFIG_DK_LIBRARY=y

# Enable Device Information Service (DIS)
CONFIG_BT_DIS=y
CONFIG_BT_DIS_MANUF="RTL"
CONFIG_BT_DIS_MODEL="CAB"
CONFIG_BT_DIS_HW_REV=y
CONFIG_BT_DIS_HW_REV_STR="1.0.1"
CONFIG_BT_DIS_SW_REV=y
CONFIG_BT_DIS_SW_REV_STR="Bootloader: 1.0.1, SoftDevice: 6.1.0, Application: 2.0.12"

# Enable Battery Service (BAS)
CONFIG_BT_BAS=y
CONFIG_BT_BAS_LOG_LEVEL_DBG=y

# Enable ADC for battery measurement
CONFIG_ADC=y

# Increase stack size for the main thread and System Workqueue
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
CONFIG_MAIN_STACK_SIZE=2048

# Enable PWM
CONFIG_LED=y
CONFIG_PWM=y
CONFIG_LED_PWM=y
CONFIG_TIMER=y
CONFIG_PWM_LOG_LEVEL_DBG=y

Parents
  • That is because you did not declare the characteristic properly

    Change

    BT_GATT_PRIMARY_SERVICE(BT_UUID_CAB),
    		    BT_GATT_CHARACTERISTIC(BT_UUID_EMERGENCY_VAL, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,

    to 

    BT_GATT_PRIMARY_SERVICE(BT_UUID_CAB),
    		    BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(BT_UUID_EMERGENCY_VAL), BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,

    The main difference is that BT_UUID_EMERGENCY_VAL needs be declared using teh macro BT_UUID_DECLARE_128

    BT_UUID_DECLARE_128(BT_UUID_EMERGENCY_VAL)
Reply
  • That is because you did not declare the characteristic properly

    Change

    BT_GATT_PRIMARY_SERVICE(BT_UUID_CAB),
    		    BT_GATT_CHARACTERISTIC(BT_UUID_EMERGENCY_VAL, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,

    to 

    BT_GATT_PRIMARY_SERVICE(BT_UUID_CAB),
    		    BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(BT_UUID_EMERGENCY_VAL), BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,

    The main difference is that BT_UUID_EMERGENCY_VAL needs be declared using teh macro BT_UUID_DECLARE_128

    BT_UUID_DECLARE_128(BT_UUID_EMERGENCY_VAL)
Children
Related