<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>max30102 sensor with NUS Service using zephyr</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/111209/max30102-sensor-with-nus-service-using-zephyr</link><description>Hi all, 
 Could anyone share a code example for sending sensor data over BLE using the NUS Service in Zephyr RTOS? I&amp;#39;m new to this field and struggling to get data from the MAX30102 sensor over BLE. If you could provide any samples, I would greatly appreciate</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Wed, 22 May 2024 11:17:09 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/111209/max30102-sensor-with-nus-service-using-zephyr" /><item><title>RE: max30102 sensor with NUS Service using zephyr</title><link>https://devzone.nordicsemi.com/thread/485377?ContentTypeID=1</link><pubDate>Wed, 22 May 2024 11:17:09 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:29581074-af11-416e-bfc2-a13e6137d8ed</guid><dc:creator>Naeem Maroof</dc:creator><description>&lt;p&gt;Hi Fernando,&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Which sensor you are using and how you are connecting to the hardware?&lt;/p&gt;
&lt;p&gt;How does your overlay file look like. Also indicate about the prj.conf.&lt;/p&gt;
&lt;p&gt;I see in your main file you are calling &amp;quot;&lt;span&gt;max_init()&lt;/span&gt;&amp;quot;, but I don&amp;#39;t see it in your &amp;quot;max.c&amp;quot; file.&lt;/p&gt;
&lt;p&gt;Can you send your minimal project, that as you have said would compile. Also indicate details about your sensor and the connections.&lt;/p&gt;
&lt;p&gt;Mention the NCS version and the DK / board that you are using.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Regards,&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: max30102 sensor with NUS Service using zephyr</title><link>https://devzone.nordicsemi.com/thread/484702?ContentTypeID=1</link><pubDate>Thu, 16 May 2024 13:22:31 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:31a56163-e9d2-4b61-9f16-cab390d16521</guid><dc:creator>Fernando@Madusha</dc:creator><description>&lt;p&gt;Hi&amp;nbsp;&lt;span&gt;Hieu,&lt;br /&gt;&lt;br /&gt;Thank you for your reply&lt;br /&gt;&lt;br /&gt;No there is no error showing its&amp;nbsp; &amp;quot;Starting Nordic UART service example&amp;quot;&amp;nbsp; and I can connect the peripheral through the nrf connect mobile app.&lt;br /&gt;But it I could not get the sensor data here my max.c and max.h file&lt;br /&gt;Please help for get the sensor data thank you again.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Best regards,&lt;br /&gt;Madusha Fernando&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#ifndef MAX_H
#define MAX_H

#include &amp;lt;zephyr/kernel.h&amp;gt;
#include &amp;lt;zephyr/device.h&amp;gt;
#include &amp;lt;zephyr/devicetree.h&amp;gt;
#include &amp;lt;zephyr/drivers/i2c.h&amp;gt;
#include &amp;lt;zephyr/sys/printk.h&amp;gt;

/* Device-specific register addresses and settings */
#define MAX30102_ADDRESS     0x57
#define INT_ENABLE_1         0xC0
#define INT_ENABLE_2         0x00
#define FIFO_WR_PTR          0x00
#define OVERFLOW_CTR         0x00
#define FIFO_RD_PTR          0x00        
#define FIFO_CONF            0x4F
#define SPO2_CONF            0x27
#define MODE_CONF            0x40
#define INT_STATUS_1         0x00
#define INT_STATUS_2         0x01
#define MAX30102_REG_FIFO_DATA  0x07 
#define MAX30102_REG_LED1_PA 0x0C
#define MAX30102_REG_LED2_PA 0x0D
#define MAX30102_REG_MODE_CONFIGURATION 0x09
#define MAX30102_RESET 0x40

/* Node identifier for the sensor */
#define I2C_NODE DT_NODELABEL(mysensor)

/* Function prototypes */
int max30102_init(const struct device *dev);
int max30102_read_fifo(const struct device *dev, uint32_t *red_led, uint32_t *ir_led);

int ble_init(void);

struct sensor_data_t {
    uint32_t red_led;
    uint32_t ir_led;
} __packed;

#endif /* MAX_H */
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#include &amp;lt;zephyr/kernel.h&amp;gt;
#include &amp;lt;zephyr/device.h&amp;gt;
#include &amp;lt;zephyr/devicetree.h&amp;gt;
#include &amp;lt;zephyr/drivers/i2c.h&amp;gt;
#include &amp;lt;zephyr/sys/printk.h&amp;gt;

#include &amp;quot;max.h&amp;quot;

/* Define a variable to hold the NUS instance */
static struct bt_nus_cb nus_cb;

/* Define a variable to hold BLE data */
static struct ble_data_t ble_data;

/* Callback function to handle BLE data received event */
static ssize_t ble_data_received(struct bt_conn *conn, const struct bt_gatt_attr *attr,
				  const void *buf, uint16_t len, uint16_t offset, uint8_t flags)
{
	/* Handle received data if needed */
	return len;
}

/* BLE initialization function */
int ble_init(void)
{
	int err;

	err = bt_enable(NULL);
	if (err) {
		printk(&amp;quot;Bluetooth init failed (err %d)\n&amp;quot;, err);
		return err;
	}

	printk(&amp;quot;Bluetooth initialized\n&amp;quot;);

	bt_nus_init(&amp;amp;nus_cb);

	/* Register callback for data received event */
	nus_cb.received = ble_data_received;

	return 0;
}

/* Initialize the MAX30102 sensor */
int max30102_init(const struct device *dev)
{
    int ret;
    
    if (!device_is_ready(dev)) {
        printk(&amp;quot;I2C bus %s is not ready!\n&amp;quot;, dev-&amp;gt;name);
        return -1;
    }

    uint8_t config[4] = {MAX30102_RESET, MAX30102_REG_MODE_CONFIGURATION, MODE_CONF, 0x40};
    ret = i2c_write(dev, config, sizeof(config), MAX30102_ADDRESS);
    if (ret != 0) {
        printk(&amp;quot;Failed to write to I2C device address %x at Reg. %x \n&amp;quot;, MAX30102_ADDRESS, config[0]);
        return -1;
    }

    k_msleep(100);

    uint8_t setup_registers[] = {
        INT_ENABLE_1, 0xC0,
        INT_ENABLE_2, 0x00,
        FIFO_WR_PTR, 0x00,
        OVERFLOW_CTR, 0x00,
        FIFO_RD_PTR, 0x00,
        FIFO_CONF, 0x5F,
        SPO2_CONF, 0x27,
        MAX30102_REG_LED1_PA, 0x1F,
        MAX30102_REG_LED2_PA, 0x1F,
        MAX30102_REG_MODE_CONFIGURATION, 0x03
    };

    ret = i2c_write(dev, setup_registers, sizeof(setup_registers), MAX30102_ADDRESS);
    if (ret != 0) {
        printk(&amp;quot;Failed to write setup registers to MAX30102\n&amp;quot;);
        return -1;
    }

    /* Initialize BLE */
    ble_init();

    return 0;
}

/* Read sensor data from MAX30102 sensor and transmit over BLE */
int max30102_read_fifo(const struct device *dev, uint32_t *red_led, uint32_t *ir_led)
{
    int ret;
    uint8_t data_array[6];

    ret = i2c_burst_read(dev, MAX30102_ADDRESS, MAX30102_REG_FIFO_DATA, data_array, sizeof(data_array));
    if (ret != 0) {
        printk(&amp;quot;Failed to read FIFO data from I2C device address %x\n&amp;quot;, MAX30102_ADDRESS);
        return -1;
    }

    *red_led = (data_array[0] &amp;lt;&amp;lt; 16) | (data_array[1] &amp;lt;&amp;lt; 8) | data_array[2];
    *ir_led = (data_array[3] &amp;lt;&amp;lt; 16) | (data_array[4] &amp;lt;&amp;lt; 8) | data_array[5];

    /* Populate BLE data */
    ble_data.red_led = *red_led;
    ble_data.ir_led = *ir_led;

    /* Transmit BLE data using NUS */
    bt_nus_send(NULL, &amp;amp;ble_data, sizeof(ble_data));

    return 0;
}
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: max30102 sensor with NUS Service using zephyr</title><link>https://devzone.nordicsemi.com/thread/484654?ContentTypeID=1</link><pubDate>Thu, 16 May 2024 11:19:35 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:ab169539-1d56-4c8e-83f7-af5ac6c575b2</guid><dc:creator>Hieu</dc:creator><description>&lt;p&gt;Hi Fernando,&lt;/p&gt;
&lt;p&gt;Have you checked that the sensor data you have here is good, and if bt_nus_send returns any error? I am talking about the code between line 594 and 597.&lt;/p&gt;
&lt;p&gt;Hieu&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;span&gt;Please be informed that&amp;nbsp;due to&amp;nbsp;a short holiday,&amp;nbsp;there will be some delays in our responses in the coming days. Our apologies for the inconvenience.&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: max30102 sensor with NUS Service using zephyr</title><link>https://devzone.nordicsemi.com/thread/483540?ContentTypeID=1</link><pubDate>Wed, 15 May 2024 14:07:48 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:ef59ddb6-f54d-4e19-a406-c4b9ffbab789</guid><dc:creator>Fernando@Madusha</dc:creator><description>&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;/*
 * Copyright (c) 2018 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
 */

/** @file
 *  @brief Nordic UART Bridge Service (NUS) sample
 */
#include &amp;quot;uart_async_adapter.h&amp;quot;

#include &amp;lt;zephyr/types.h&amp;gt;
#include &amp;lt;zephyr/kernel.h&amp;gt;
#include &amp;lt;zephyr/drivers/uart.h&amp;gt;
#include &amp;lt;zephyr/usb/usb_device.h&amp;gt;

#include &amp;lt;zephyr/device.h&amp;gt;
#include &amp;lt;zephyr/devicetree.h&amp;gt;
#include &amp;lt;soc.h&amp;gt;

#include &amp;lt;zephyr/bluetooth/bluetooth.h&amp;gt;
#include &amp;lt;zephyr/bluetooth/uuid.h&amp;gt;
#include &amp;lt;zephyr/bluetooth/gatt.h&amp;gt;
#include &amp;lt;zephyr/bluetooth/hci.h&amp;gt;

#include &amp;lt;bluetooth/services/nus.h&amp;gt;

#include &amp;lt;dk_buttons_and_leds.h&amp;gt;

#include &amp;lt;zephyr/settings/settings.h&amp;gt;

#include &amp;lt;stdio.h&amp;gt;

#include &amp;lt;zephyr/logging/log.h&amp;gt;
#include &amp;quot;max.h&amp;quot;
#include &amp;lt;zephyr/kernel.h&amp;gt;
#include &amp;lt;zephyr/device.h&amp;gt;
#include &amp;lt;zephyr/devicetree.h&amp;gt;
#include &amp;quot;max.h&amp;quot;
#define SLEEP_TIME_MS 1000

LOG_MODULE_REGISTER(Lesson4_Exercise3, LOG_LEVEL_INF);

#define STACKSIZE CONFIG_BT_NUS_THREAD_STACK_SIZE
#define PRIORITY 7

#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)

#define RUN_STATUS_LED DK_LED1
#define RUN_LED_BLINK_INTERVAL 1000

#define CON_STATUS_LED DK_LED2

#define KEY_PASSKEY_ACCEPT DK_BTN1_MSK
#define KEY_PASSKEY_REJECT DK_BTN2_MSK

#define UART_WAIT_FOR_BUF_DELAY K_MSEC(50)
#define UART_WAIT_FOR_RX CONFIG_BT_NUS_UART_RX_WAIT_TIME

static K_SEM_DEFINE(ble_init_ok, 0, 1);

static struct bt_conn *current_conn;
static struct bt_conn *auth_conn;

static const struct device *uart = DEVICE_DT_GET(DT_CHOSEN(nordic_nus_uart));
static struct k_work_delayable uart_work;


/* STEP 6.2 - Declare the struct of the data item of the FIFOs */
struct uart_data_t {
	void *fifo_reserved;
	uint8_t data[CONFIG_BT_NUS_UART_BUFFER_SIZE];
	uint16_t len;
};

/* STEP 6.1 - Declare the FIFOs */
static K_FIFO_DEFINE(fifo_uart_tx_data);
static K_FIFO_DEFINE(fifo_uart_rx_data);

static const struct bt_data ad[] = {
	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
};

static const struct bt_data sd[] = {
	BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_NUS_VAL),
};

#if CONFIG_BT_NUS_UART_ASYNC_ADAPTER
UART_ASYNC_ADAPTER_INST_DEFINE(async_adapter);
#else
static const struct device *const async_adapter;
#endif

static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
{
	ARG_UNUSED(dev);

	static size_t aborted_len;
	struct uart_data_t *buf;
	static uint8_t *aborted_buf;
	static bool disable_req;

	switch (evt-&amp;gt;type) {
	case UART_TX_DONE:
		LOG_DBG(&amp;quot;UART_TX_DONE&amp;quot;);
		if ((evt-&amp;gt;data.tx.len == 0) || (!evt-&amp;gt;data.tx.buf)) {
			return;
		}

		if (aborted_buf) {
			buf = CONTAINER_OF(aborted_buf, struct uart_data_t,
					   data[0]);
			aborted_buf = NULL;
			aborted_len = 0;
		} else {
			buf = CONTAINER_OF(evt-&amp;gt;data.tx.buf, struct uart_data_t,
					   data[0]);
		}

		k_free(buf);

		buf = k_fifo_get(&amp;amp;fifo_uart_tx_data, K_NO_WAIT);
		if (!buf) {
			return;
		}

		if (uart_tx(uart, buf-&amp;gt;data, buf-&amp;gt;len, SYS_FOREVER_MS)) {
			LOG_WRN(&amp;quot;Failed to send data over UART&amp;quot;);
		}

		break;

	case UART_RX_RDY:
		LOG_DBG(&amp;quot;UART_RX_RDY&amp;quot;);
		buf = CONTAINER_OF(evt-&amp;gt;data.rx.buf, struct uart_data_t, data[0]);
		buf-&amp;gt;len += evt-&amp;gt;data.rx.len;

		if (disable_req) {
			return;
		}

		if ((evt-&amp;gt;data.rx.buf[buf-&amp;gt;len - 1] == &amp;#39;\n&amp;#39;) ||
		    (evt-&amp;gt;data.rx.buf[buf-&amp;gt;len - 1] == &amp;#39;\r&amp;#39;)) {
			disable_req = true;
			uart_rx_disable(uart);
		}

		break;

	case UART_RX_DISABLED:
		LOG_DBG(&amp;quot;UART_RX_DISABLED&amp;quot;);
		disable_req = false;

		buf = k_malloc(sizeof(*buf));
		if (buf) {
			buf-&amp;gt;len = 0;
		} else {
			LOG_WRN(&amp;quot;Not able to allocate UART receive buffer&amp;quot;);
			k_work_reschedule(&amp;amp;uart_work, UART_WAIT_FOR_BUF_DELAY);
			return;
		}

		uart_rx_enable(uart, buf-&amp;gt;data, sizeof(buf-&amp;gt;data), UART_WAIT_FOR_RX);

		break;

	case UART_RX_BUF_REQUEST:
		LOG_DBG(&amp;quot;UART_RX_BUF_REQUEST&amp;quot;);
		buf = k_malloc(sizeof(*buf));
		if (buf) {
			buf-&amp;gt;len = 0;
			uart_rx_buf_rsp(uart, buf-&amp;gt;data, sizeof(buf-&amp;gt;data));
		} else {
			LOG_WRN(&amp;quot;Not able to allocate UART receive buffer&amp;quot;);
		}

		break;

	case UART_RX_BUF_RELEASED:
		LOG_DBG(&amp;quot;UART_RX_BUF_RELEASED&amp;quot;);
		buf = CONTAINER_OF(evt-&amp;gt;data.rx_buf.buf, struct uart_data_t,
				   data[0]);

		if (buf-&amp;gt;len &amp;gt; 0) {
			/* STEP 9.1 -  Push the data received from the UART peripheral into the fifo_uart_rx_data FIFO */
			k_fifo_put(&amp;amp;fifo_uart_rx_data, buf);
		} else {
			k_free(buf);
		}

		break;

	case UART_TX_ABORTED:
		LOG_DBG(&amp;quot;UART_TX_ABORTED&amp;quot;);
		if (!aborted_buf) {
			aborted_buf = (uint8_t *)evt-&amp;gt;data.tx.buf;
		}

		aborted_len += evt-&amp;gt;data.tx.len;
		buf = CONTAINER_OF((void *)aborted_buf, struct uart_data_t,
				   data);

		uart_tx(uart, &amp;amp;buf-&amp;gt;data[aborted_len], buf-&amp;gt;len - aborted_len, SYS_FOREVER_MS);

		break;

	default:
		break;
	}
}

static void uart_work_handler(struct k_work *item)
{
	struct uart_data_t *buf;

	buf = k_malloc(sizeof(*buf));
	if (buf) {
		buf-&amp;gt;len = 0;
	} else {
		LOG_WRN(&amp;quot;Not able to allocate UART receive buffer&amp;quot;);
		k_work_reschedule(&amp;amp;uart_work, UART_WAIT_FOR_BUF_DELAY);
		return;
	}

	uart_rx_enable(uart, buf-&amp;gt;data, sizeof(buf-&amp;gt;data), UART_WAIT_FOR_RX);
}

static bool uart_test_async_api(const struct device *dev)
{
	const struct uart_driver_api *api = (const struct uart_driver_api *)dev-&amp;gt;api;

	return (api-&amp;gt;callback_set != NULL);
}

static int uart_init(void)
{
	int err;
	int pos;
	struct uart_data_t *rx;
	struct uart_data_t *tx;

	if (!device_is_ready(uart)) {
		return -ENODEV;
	}

	if (IS_ENABLED(CONFIG_USB_DEVICE_STACK)) {
		err = usb_enable(NULL);
		if (err &amp;amp;&amp;amp; (err != -EALREADY)) {
			LOG_ERR(&amp;quot;Failed to enable USB&amp;quot;);
			return err;
		}
	}

	rx = k_malloc(sizeof(*rx));
	if (rx) {
		rx-&amp;gt;len = 0;
	} else {
		return -ENOMEM;
	}

	k_work_init_delayable(&amp;amp;uart_work, uart_work_handler);

	if (IS_ENABLED(CONFIG_BT_NUS_UART_ASYNC_ADAPTER) &amp;amp;&amp;amp; !uart_test_async_api(uart)) {
		/* Implement API adapter */
		uart_async_adapter_init(async_adapter, uart);
		uart = async_adapter;
	}

	err = uart_callback_set(uart, uart_cb, NULL);
	if (err) {
		LOG_ERR(&amp;quot;Cannot initialize UART callback&amp;quot;);
		return err;
	}

	if (IS_ENABLED(CONFIG_UART_LINE_CTRL)) {
		LOG_INF(&amp;quot;Wait for DTR&amp;quot;);
		while (true) {
			uint32_t dtr = 0;

			uart_line_ctrl_get(uart, UART_LINE_CTRL_DTR, &amp;amp;dtr);
			if (dtr) {
				break;
			}
			/* Give CPU resources to low priority threads. */
			k_sleep(K_MSEC(100));
		}
		LOG_INF(&amp;quot;DTR set&amp;quot;);
		err = uart_line_ctrl_set(uart, UART_LINE_CTRL_DCD, 1);
		if (err) {
			LOG_WRN(&amp;quot;Failed to set DCD, ret code %d&amp;quot;, err);
		}
		err = uart_line_ctrl_set(uart, UART_LINE_CTRL_DSR, 1);
		if (err) {
			LOG_WRN(&amp;quot;Failed to set DSR, ret code %d&amp;quot;, err);
		}
	}

	tx = k_malloc(sizeof(*tx));

	if (tx) {
		pos = snprintf(tx-&amp;gt;data, sizeof(tx-&amp;gt;data),
			       &amp;quot;Starting Nordic UART service example\r\n&amp;quot;);

		if ((pos &amp;lt; 0) || (pos &amp;gt;= sizeof(tx-&amp;gt;data))) {
			k_free(tx);
			LOG_ERR(&amp;quot;snprintf returned %d&amp;quot;, pos);
			return -ENOMEM;
		}

		tx-&amp;gt;len = pos;
	} else {
		return -ENOMEM;
	}
	// Send a welcome message over UART
	err = uart_tx(uart, tx-&amp;gt;data, tx-&amp;gt;len, SYS_FOREVER_MS);
	if (err) {
		LOG_ERR(&amp;quot;Cannot display welcome message (err: %d)&amp;quot;, err);
		return err;
	}
	// Enable start receiving data over UART
	return uart_rx_enable(uart, rx-&amp;gt;data, sizeof(rx-&amp;gt;data), 50);
}

static void connected(struct bt_conn *conn, uint8_t err)
{
	char addr[BT_ADDR_LE_STR_LEN];

	if (err) {
		LOG_ERR(&amp;quot;Connection failed (err %u)&amp;quot;, err);
		return;
	}

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
	LOG_INF(&amp;quot;Connected %s&amp;quot;, addr);

	current_conn = bt_conn_ref(conn);

	dk_set_led_on(CON_STATUS_LED);
}

static void disconnected(struct bt_conn *conn, uint8_t reason)
{
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	LOG_INF(&amp;quot;Disconnected: %s (reason %u)&amp;quot;, addr, reason);

	if (auth_conn) {
		bt_conn_unref(auth_conn);
		auth_conn = NULL;
	}

	if (current_conn) {
		bt_conn_unref(current_conn);
		current_conn = NULL;
		dk_set_led_off(CON_STATUS_LED);
	}
}

#ifdef CONFIG_BT_NUS_SECURITY_ENABLED
static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err)
{
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	if (!err) {
		LOG_INF(&amp;quot;Security changed: %s level %u&amp;quot;, addr, level);
	} else {
		LOG_WRN(&amp;quot;Security failed: %s level %u err %d&amp;quot;, addr, level, err);
	}
}
#endif

BT_CONN_CB_DEFINE(conn_callbacks) = {
	.connected = connected,
	.disconnected = disconnected,
#ifdef CONFIG_BT_NUS_SECURITY_ENABLED
	.security_changed = security_changed,
#endif
};

#if defined(CONFIG_BT_NUS_SECURITY_ENABLED)
static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
{
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	LOG_INF(&amp;quot;Passkey for %s: %06u&amp;quot;, addr, passkey);
}

static void auth_passkey_confirm(struct bt_conn *conn, unsigned int passkey)
{
	char addr[BT_ADDR_LE_STR_LEN];

	auth_conn = bt_conn_ref(conn);

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	LOG_INF(&amp;quot;Passkey for %s: %06u&amp;quot;, addr, passkey);
	LOG_INF(&amp;quot;Press Button 1 to confirm, Button 2 to reject.&amp;quot;);
}

static void auth_cancel(struct bt_conn *conn)
{
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	LOG_INF(&amp;quot;Pairing cancelled: %s&amp;quot;, addr);
}

static void pairing_complete(struct bt_conn *conn, bool bonded)
{
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	LOG_INF(&amp;quot;Pairing completed: %s, bonded: %d&amp;quot;, addr, bonded);
}

static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
{
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	LOG_INF(&amp;quot;Pairing failed conn: %s, reason %d&amp;quot;, addr, reason);
}

static struct bt_conn_auth_cb conn_auth_callbacks = {
	.passkey_display = auth_passkey_display,
	.passkey_confirm = auth_passkey_confirm,
	.cancel = auth_cancel,
};

static struct bt_conn_auth_info_cb conn_auth_info_callbacks = { .pairing_complete =
									pairing_complete,
								.pairing_failed = pairing_failed };
#else
static struct bt_conn_auth_cb conn_auth_callbacks;
static struct bt_conn_auth_info_cb conn_auth_info_callbacks;
#endif

static void bt_receive_cb(struct bt_conn *conn, const uint8_t *const data, uint16_t len)
{
	int err;
	char addr[BT_ADDR_LE_STR_LEN] = { 0 };

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, ARRAY_SIZE(addr));

	LOG_INF(&amp;quot;Received data from: %s&amp;quot;, addr);

	for (uint16_t pos = 0; pos != len;) {
		struct uart_data_t *tx = k_malloc(sizeof(*tx));

		if (!tx) {
			LOG_WRN(&amp;quot;Not able to allocate UART send data buffer&amp;quot;);
			return;
		}

		/* Keep the last byte of TX buffer for potential LF char. */
		size_t tx_data_size = sizeof(tx-&amp;gt;data) - 1;

		if ((len - pos) &amp;gt; tx_data_size) {
			tx-&amp;gt;len = tx_data_size;
		} else {
			tx-&amp;gt;len = (len - pos);
		}

		memcpy(tx-&amp;gt;data, &amp;amp;data[pos], tx-&amp;gt;len);

		pos += tx-&amp;gt;len;

		/* Append the LF character when the CR character triggered
		 * transmission from the peer.
		 */
		if ((pos == len) &amp;amp;&amp;amp; (data[len - 1] == &amp;#39;\r&amp;#39;)) {
			tx-&amp;gt;data[tx-&amp;gt;len] = &amp;#39;\n&amp;#39;;
			tx-&amp;gt;len++;
		}
		/* STEP 8.3 - Forward the data received over Bluetooth LE to the UART peripheral */
		err = uart_tx(uart, tx-&amp;gt;data, tx-&amp;gt;len, SYS_FOREVER_MS);
		if (err) {
			k_fifo_put(&amp;amp;fifo_uart_tx_data, tx);
		}
	}
}
/* STEP 8.1 - Create a variable of type bt_nus_cb and initialize it */
static struct bt_nus_cb nus_cb = {
	.received = bt_receive_cb,
};

void error(void)
{
	dk_set_leds_state(DK_ALL_LEDS_MSK, DK_NO_LEDS_MSK);

	while (true) {
		/* Spin for ever */
		k_sleep(K_MSEC(1000));
	}
}

#ifdef CONFIG_BT_NUS_SECURITY_ENABLED
static void num_comp_reply(bool accept)
{
	if (accept) {
		bt_conn_auth_passkey_confirm(auth_conn);
		LOG_INF(&amp;quot;Numeric Match, conn %p&amp;quot;, (void *)auth_conn);
	} else {
		bt_conn_auth_cancel(auth_conn);
		LOG_INF(&amp;quot;Numeric Reject, conn %p&amp;quot;, (void *)auth_conn);
	}

	bt_conn_unref(auth_conn);
	auth_conn = NULL;
}

void button_changed(uint32_t button_state, uint32_t has_changed)
{
	uint32_t buttons = button_state &amp;amp; has_changed;

	if (auth_conn) {
		if (buttons &amp;amp; KEY_PASSKEY_ACCEPT) {
			num_comp_reply(true);
		}

		if (buttons &amp;amp; KEY_PASSKEY_REJECT) {
			num_comp_reply(false);
		}
	}
}
#endif /* CONFIG_BT_NUS_SECURITY_ENABLED */

static void configure_gpio(void)
{
	int err;

#ifdef CONFIG_BT_NUS_SECURITY_ENABLED
	err = dk_buttons_init(button_changed);
	if (err) {
		LOG_ERR(&amp;quot;Cannot init buttons (err: %d)&amp;quot;, err);
	}
#endif /* CONFIG_BT_NUS_SECURITY_ENABLED */

	err = dk_leds_init();
	if (err) {
		LOG_ERR(&amp;quot;Cannot init LEDs (err: %d)&amp;quot;, err);
	}
}
static void bt_ready(int err)
{
    if (err) {
        LOG_ERR(&amp;quot;Bluetooth init failed (err %d)&amp;quot;, err);
        return;
    }
    LOG_INF(&amp;quot;Bluetooth initialized&amp;quot;);
    err = bt_nus_init(&amp;amp;nus_cb);
    if (err) {
        LOG_ERR(&amp;quot;Failed to init NUS (err: %d)&amp;quot;, err);
        return;
    }
    err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
    if (err) {
        LOG_ERR(&amp;quot;Advertising failed to start (err %d)&amp;quot;, err);
        return;
    }
    LOG_INF(&amp;quot;Advertising successfully started&amp;quot;);
    k_sem_give(&amp;amp;ble_init_ok);
}

void max30102_thread(void)
{
    // Initialize the MAX30102 sensor
    int ret = max_init();
    if (ret != 0) {
        LOG_ERR(&amp;quot;Failed to initialize MAX30102 sensor&amp;quot;);
        return;
    }
    
    while (1) {
        // Read data from the MAX30102 sensor
        uint32_t red, ir;
        ret = max_read_fifo(&amp;amp;red, &amp;amp;ir);
        if (ret != 0) {
            LOG_ERR(&amp;quot;Failed to read from MAX30102 sensor&amp;quot;);
            continue;
        }

        // Send the sensor data over NUS
        char sensor_data[32];
        snprintf(sensor_data, sizeof(sensor_data), &amp;quot;RED: %u, IR: %u\n&amp;quot;, red, ir);
        bt_nus_send(current_conn, sensor_data, strlen(sensor_data));
        
        // Delay before the next read
        k_sleep(K_MSEC(SLEEP_TIME_MS));
    }
}

int main(void)
{   
  
	
	int blink_status = 0;
	int err = 0;

	configure_gpio();
	/* STEP 7 - Initialize the UART Peripheral  */
	err = uart_init();
	if (err) {
		error();
	}

	if (IS_ENABLED(CONFIG_BT_NUS_SECURITY_ENABLED)) {
		err = bt_conn_auth_cb_register(&amp;amp;conn_auth_callbacks);
		if (err) {
			LOG_ERR(&amp;quot;Failed to register authorization callbacks.\n&amp;quot;);
			return -1;
		}

		err = bt_conn_auth_info_cb_register(&amp;amp;conn_auth_info_callbacks);
		if (err) {
			LOG_ERR(&amp;quot;Failed to register authorization info callbacks.\n&amp;quot;);
			return -1;
		}
	}

	err = bt_enable(NULL);
	if (err) {
		error();
	}

	LOG_INF(&amp;quot;Bluetooth initialized&amp;quot;);

	k_sem_give(&amp;amp;ble_init_ok);

	if (IS_ENABLED(CONFIG_SETTINGS)) {
		settings_load();
	}
	/* STEP 8.2 - Pass your application callback function to the NUS service */
	err = bt_nus_init(&amp;amp;nus_cb);
	if (err) {
		LOG_ERR(&amp;quot;Failed to initialize UART service (err: %d)&amp;quot;, err);
		return -1;
	}

	err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
	if (err) {
		LOG_ERR(&amp;quot;Advertising failed to start (err %d)&amp;quot;, err);
		return -1;
	}

	for (;;) {
		dk_set_led(RUN_STATUS_LED, (++blink_status) % 2);
		k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL));
	}
}


/* STEP 9.3 - Define the thread function  */
void ble_write_thread(void)
{
	/* Don&amp;#39;t go any further until BLE is initialized */
	k_sem_take(&amp;amp;ble_init_ok, K_FOREVER);

	for (;;) {

		
		/* Wait indefinitely for data from the UART peripheral */
		struct uart_data_t *buf = k_fifo_get(&amp;amp;fifo_uart_rx_data, K_FOREVER);
		/* Send data over Bluetooth LE to remote device(s) */
		if (bt_nus_send(NULL, buf-&amp;gt;data, buf-&amp;gt;len)) {
			LOG_WRN(&amp;quot;Failed to send data over BLE connection&amp;quot;);
		}

		k_free(buf);
	}
}
/* STEP 9.2 - Create a dedicated thread for sending the data over Bluetooth LE. */
K_THREAD_DEFINE(ble_write_thread_id, STACKSIZE, ble_write_thread, NULL, NULL, NULL, PRIORITY, 0, 0);
&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>