How to print RSSI value of all the advertising packets from peripheral to central and print on PuTTy.

Hi,

I'm working on central_uart and peripheral_uart examples. I want to get the rssi value and tx_power of all advertising packets from peripheral to central via bluetooth connection. How can i get these values and print the same on the PuTTy terminal.

Can you please guide me with all the functions i need to involve in the peripheral or central main functions.

Regards

Karthik Kumar

Parents
  • Hello!

    As I suggested in one of your previous cases, there is a sample that demonstrates how to handle these values:

    https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/samples/bluetooth/hci_pwr_ctrl/README.html

    This sample shows you how to read the values, and once you've done that you can send them to your central which can print them with printk.

    Best regards,

    Einar

  • Hi,

    I have made these modification on the peripheral uart file which are in red coloured text.


    static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
    {
        ARG_UNUSED(dev);

        static uint8_t *current_buf;
        static size_t aborted_len;
        static bool buf_release;
        struct uart_data_t *buf;
        static uint8_t *aborted_buf;

        switch (evt->type) {
        case UART_TX_DONE:
            LOG_DBG("tx_done");
            printk("tx_done\n");
            if ((evt->data.tx.len == 0) ||
                (!evt->data.tx.buf)) {
                return;
            }

            if (aborted_buf) {
                buf = CONTAINER_OF(aborted_buf, struct uart_data_t,
                           data);
                aborted_buf = NULL;
                aborted_len = 0;
            } else {
                buf = CONTAINER_OF(evt->data.tx.buf, struct uart_data_t,
                           data);
            }

            k_free(buf);

            buf = k_fifo_get(&fifo_uart_tx_data, K_NO_WAIT);
            if (!buf) {
                return;
            }

            if (uart_tx(uart, buf->data, buf->len, SYS_FOREVER_MS)) {
                LOG_WRN("Failed to send data over UART");
                printk("Failed to send data over UART\n");
            }

            break;

        case UART_RX_RDY:
            LOG_DBG("rx_rdy");
            printk("rx_rdy\n");
            buf = CONTAINER_OF(evt->data.rx.buf, struct uart_data_t, data);
            buf->len += evt->data.rx.len;
            buf_release = false;

            if (buf->len == UART_BUF_SIZE) {
                k_fifo_put(&fifo_uart_rx_data, buf);
            } else if ((evt->data.rx.buf[buf->len - 1] == '\n') ||
                  (evt->data.rx.buf[buf->len - 1] == '\r')) {
                k_fifo_put(&fifo_uart_rx_data, buf);
                current_buf = evt->data.rx.buf;
                buf_release = true;
                uart_rx_disable(uart);
            }

            break;

        case UART_RX_DISABLED:
            LOG_DBG("rx_disabled");
            printk("rx_disabled\n");
            buf = k_malloc(sizeof(*buf));
            if (buf) {
                buf->len = 0;
            } else {
                LOG_WRN("Not able to allocate UART receive buffer");
                printk("Not able to allocate UART receive buffer\n");
                k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
                return;
            }

            uart_rx_enable(uart, buf->data, sizeof(buf->data),
                       UART_WAIT_FOR_RX);

            break;

        case UART_RX_BUF_REQUEST:
            LOG_DBG("rx_buf_request");
            printk("rx_buf_request\n");
            buf = k_malloc(sizeof(*buf));
            if (buf) {
                buf->len = 0;
                uart_rx_buf_rsp(uart, buf->data, sizeof(buf->data));
            } else {
                LOG_WRN("Not able to allocate UART receive buffer");
                printk("Not able to allocate UART receive buffer\n");
            }

            break;

        case UART_RX_BUF_RELEASED:
            LOG_DBG("rx_buf_released");
            printk("rx_buf_released\n");
            buf = CONTAINER_OF(evt->data.rx_buf.buf, struct uart_data_t,
                       data);
            if (buf_release && (current_buf != evt->data.rx_buf.buf)) {
                k_free(buf);
                buf_release = false;
                current_buf = NULL;
            }

            break;

        case UART_TX_ABORTED:
                LOG_DBG("tx_aborted");
                printk("tx_aborted\n");
                if (!aborted_buf) {
                    aborted_buf = (uint8_t *)evt->data.tx.buf;
                }

                aborted_len += evt->data.tx.len;
                buf = CONTAINER_OF(aborted_buf, struct uart_data_t,
                           data);

                uart_tx(uart, &buf->data[aborted_len],
                    buf->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->len = 0;
        } else {
            LOG_WRN("Not able to allocate UART receive buffer");
            printk("Not able to allocate UART receive buffer\n");
            k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
            return;
        }

        uart_rx_enable(uart, buf->data, sizeof(buf->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->api;

        return (api->callback_set != NULL);
    }

    static int uart_init(void)
    {
        int err;
        int pos;
        struct uart_data_t *rx;
        struct uart_data_t *tx;

        uart = device_get_binding(CONFIG_BT_NUS_UART_DEV);
        if (!uart) {
            return -ENXIO;
        }

        if (IS_ENABLED(CONFIG_USB_DEVICE_STACK)) {
            err = usb_enable(NULL);
            if (err) {
                LOG_ERR("Failed to enable USB");
                printk("Failed to enable USB\n");
                return err;
            }
        }

        rx = k_malloc(sizeof(*rx));
        if (rx) {
            rx->len = 0;
        } else {
            return -ENOMEM;
        }

        k_work_init_delayable(&uart_work, uart_work_handler);


        if (IS_ENABLED(CONFIG_BT_NUS_UART_ASYNC_ADAPTER) && !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("Cannot initialize UART callback");
            printk("Cannot initialize UART callback\n");
            return err;
        }

        if (IS_ENABLED(CONFIG_UART_LINE_CTRL)) {
            LOG_INF("Wait for DTR");
            printk("Wait for DTR\n");
            while (true) {
                uint32_t dtr = 0;

                uart_line_ctrl_get(uart, UART_LINE_CTRL_DTR, &dtr);
                if (dtr) {
                    break;
                }
                /* Give CPU resources to low priority threads. */
                k_sleep(K_MSEC(100));
            }
            LOG_INF("DTR set");
            printk("DTR set\n");
            err = uart_line_ctrl_set(uart, UART_LINE_CTRL_DCD, 1);
            if (err) {
                LOG_WRN("Failed to set DCD, ret code %d", err);
                printk("Failed to set DCD, ret code %d\n", err);
            }
            err = uart_line_ctrl_set(uart, UART_LINE_CTRL_DSR, 1);
            if (err) {
                LOG_WRN("Failed to set DSR, ret code %d", err);
                printk("Failed to set DSR, ret code %d\n", err);
            }
        }

        tx = k_malloc(sizeof(*tx));

        if (tx) {
            pos = snprintf(tx->data, sizeof(tx->data),
                       "Starting Nordic UART service example\r\n");

            if ((pos < 0) || (pos >= sizeof(tx->data))) {
                k_free(tx);
                LOG_ERR("snprintf returned %d", pos);
                printk("snprintf returned %d\n", pos);
                return -ENOMEM;
            }

            tx->len = pos;
        } else {
            return -ENOMEM;
        }

        err = uart_tx(uart, tx->data, tx->len, SYS_FOREVER_MS);
        if (err) {
            LOG_ERR("Cannot display welcome message (err: %d)", err);
            printk("Cannot display welcome message (err: %d)\n", err);
            return err;
        }

        return uart_rx_enable(uart, rx->data, sizeof(rx->data), 50);
    }
    /*
    Reading RSSI Value
    */
    static void read_conn_rssi(uint16_t handle, int8_t *rssi)
    {
        struct net_buf *buf, *rsp = NULL;
        struct bt_hci_cp_read_rssi *cp;
        struct bt_hci_rp_read_rssi *rp;

        int err;

        buf = bt_hci_cmd_create(BT_HCI_OP_READ_RSSI, sizeof(*cp));
        if (!buf) {
            printk("Unable to allocate command buffer\n");
            return;
        }

        cp = net_buf_add(buf, sizeof(*cp));
        cp->handle = sys_cpu_to_le16(handle);

        err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_RSSI, buf, &rsp);
        if (err) {
            uint8_t reason = rsp ?
                ((struct bt_hci_rp_read_rssi *)rsp->data)->status : 0;
            printk("Read RSSI err: %d reason 0x%02x\n", err, reason);
            return;
        }

        rp = (void *)rsp->data;
        *rssi = rp->rssi;

        net_buf_unref(rsp);
    }
    //uint32_t sd_ble_gap_rssi_start    ( conn_handle, BLE_GAP_EVT_RSSI_CHANGED, BLE_GAP_EVT_RSSI_CHANGED);
    //uint32_t sd_ble_gap_rssi_get  (conn_handle, BLE_GAP_EVT_RSSI_CHANGED, BLE_GAP_EVT_RSSI_CHANGED);
    /* TX Power*/

    static void set_tx_power(uint8_t handle_type, uint16_t handle, int8_t tx_pwr_lvl)
    {
        struct bt_hci_cp_vs_write_tx_power_level *cp;
        struct bt_hci_rp_vs_write_tx_power_level *rp;
        struct net_buf *buf, *rsp = NULL;
        int err;

        buf = bt_hci_cmd_create(BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL,
                    sizeof(*cp));
        if (!buf) {
            printk("Unable to allocate command buffer\n");
            return;
        }

        cp = net_buf_add(buf, sizeof(*cp));
        cp->handle = sys_cpu_to_le16(handle);
        cp->handle_type = handle_type;
        cp->tx_power_level = tx_pwr_lvl;

        err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL,
                       buf, &rsp);
        if (err) {
            uint8_t reason = rsp ?
                ((struct bt_hci_rp_vs_write_tx_power_level *)
                  rsp->data)->status : 0;
            printk("Set Tx power err: %d reason 0x%02x\n", err, reason);
            return;
        }

        rp = (void *)rsp->data;
        printk("Actual Tx Power: %d\n", rp->selected_tx_power);

        net_buf_unref(rsp);
    }


    static void get_tx_power(uint8_t handle_type, uint16_t handle, int8_t *tx_pwr_lvl)
    {
        struct bt_hci_cp_vs_read_tx_power_level *cp;
        struct bt_hci_rp_vs_read_tx_power_level *rp;
        struct net_buf *buf, *rsp = NULL;
        int err;

        *tx_pwr_lvl = 0xFF;
        buf = bt_hci_cmd_create(BT_HCI_OP_VS_READ_TX_POWER_LEVEL,
                    sizeof(*cp));
        if (!buf) {
            printk("Unable to allocate command buffer\n");
            return;
        }

        cp = net_buf_add(buf, sizeof(*cp));
        cp->handle = sys_cpu_to_le16(handle);
        cp->handle_type = handle_type;

        err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_TX_POWER_LEVEL,
                       buf, &rsp);
        if (err) {
            uint8_t reason = rsp ?
                ((struct bt_hci_rp_vs_read_tx_power_level *)
                  rsp->data)->status : 0;
            printk("Read Tx power (Maximum): %d reason 0x%02x\n", err, reason);
            return;
        }

        rp = (void *)rsp->data;
        *tx_pwr_lvl = rp->tx_power_level;

        net_buf_unref(rsp);
    }

    /*connection*/
    static void connected(struct bt_conn *conn, uint8_t conn_err)
    {
        int err;
        int8_t txp;
        struct bt_conn_info info;
        char addr[BT_ADDR_LE_STR_LEN];

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

        if (conn_err) {
            LOG_ERR("Connection failed (err %u)", conn_err);
            printk("Connection failed (err %u)\n", conn_err);
            return;
        }

        /*bt_addr_le_to_str(bt_conn_foreach(conn), addr, sizeof(addr));*/
            err = bt_conn_get_info(conn, &info);

        if (err) {
            printk("Failed to get connection info\n");
        }
         else {
            const struct bt_conn_le_phy_info *phy_info;
            phy_info = BT_CONN_LE_PHY_OPT_CODED_S8;
            get_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_CONN,
                         NULL, &txp);
            LOG_INF("Connected: %s, tx_phy %u, rx_phy %u ,Initial Tx Power = %d",
                   log_strdup(addr), phy_info->tx_phy, phy_info->rx_phy, txp);

            printk("Coded PHY Connected: %s, tx_phy %u, rx_phy %u, Initial Tx Power = %d\n",
                   log_strdup(addr), phy_info->tx_phy, phy_info->rx_phy, txp);
                   //printk(NRF_RADIO->RSSISAMPLE);
                   //uint32_t sd_ble_gap_rssi_start ( conn_handle, 0, 0)
         }

        current_conn = bt_conn_ref(conn);
        /*current_conn = bt_conn_foreach(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));
        /*bt_addr_le_to_str(bt_conn_foreach(conn), addr, sizeof(addr));*/

        LOG_INF("Disconnected: %s (reason %u)", log_strdup(addr), reason);
        printk("Disconnected: %s (reason %u)\n", log_strdup(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("Security changed: %s level %u", log_strdup(addr),
                level);
                printk("Security changed: %s level %u\n", log_strdup(addr),
                level);
        } else {
            LOG_WRN("Security failed: %s level %u err %d", log_strdup(addr),
                level, err);
                printk("Security failed: %s level %u err %d\n", log_strdup(addr),
                level, err);
        }
    }
    #endif

    static struct bt_conn_cb 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("Passkey for %s: %06u", log_strdup(addr), passkey);
        printk("Passkey for %s: %06u\n", log_strdup(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("Passkey for %s: %06u", log_strdup(addr), passkey);
        printk("Passkey for %s: %06u\n", log_strdup(addr), passkey);
        LOG_INF("Press Button 1 to confirm, Button 2 to reject.");
        printk("Press Button 1 to confirm, Button 2 to reject.\n");
    }


    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("Pairing cancelled: %s", log_strdup(addr));
        printk("Pairing cancelled: %s\n", log_strdup(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("Pairing completed: %s, bonded: %d", log_strdup(addr),
            bonded);
            printk("Pairing completed: %s, bonded: %d\n", log_strdup(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("Pairing failed conn: %s, reason %d", log_strdup(addr),
            reason);
            printk("Pairing failed conn: %s, reason %d\n", log_strdup(addr),
            reason);
    }


    static struct bt_conn_auth_cb conn_auth_callbacks = {
        .passkey_display = auth_passkey_display,
        .passkey_confirm = auth_passkey_confirm,
        .cancel = auth_cancel,
        .pairing_complete = pairing_complete,
        .pairing_failed = pairing_failed
    };
    #else
    static struct bt_conn_auth_cb conn_auth_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("Received data from: %s", log_strdup(addr));
        printk("Received data from: %s\n", log_strdup(addr));

        for (uint16_t pos = 0; pos != len;) {
            struct uart_data_t *tx = k_malloc(sizeof(*tx));

            if (!tx) {
                LOG_WRN("Not able to allocate UART send data buffer");
                printk("Not able to allocate UART send data buffer\n");
                return;
            }

            /* Keep the last byte of TX buffer for potential LF char. */
            size_t tx_data_size = sizeof(tx->data) - 1;

            if ((len - pos) > tx_data_size) {
                tx->len = tx_data_size;
            } else {
                tx->len = (len - pos);
            }

            memcpy(tx->data, &data[pos], tx->len);

            pos += tx->len;

            /* Append the LF character when the CR character triggered
             * transmission from the peer.
             */
            if ((pos == len) && (data[len - 1] == '\r')) {
                tx->data[tx->len] = '\n';
                tx->len++;
            }

            err = uart_tx(uart, tx->data, tx->len, SYS_FOREVER_MS);
            if (err) {
                k_fifo_put(&fifo_uart_tx_data, tx);
            }
        }
    }

    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("Numeric Match, conn %p", (void *)auth_conn);
            printk("Numeric Match, conn %p\n", (void *)auth_conn);
        } else {
            bt_conn_auth_cancel(auth_conn);
            LOG_INF("Numeric Reject, conn %p", (void *)auth_conn);
            printk("Numeric Reject, conn %p\n", (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 & has_changed;

        if (auth_conn) {
            if (buttons & KEY_PASSKEY_ACCEPT) {
                num_comp_reply(true);
            }

            if (buttons & 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("Cannot init buttons (err: %d)", err);
            printk("Cannot init buttons (err: %d)\n", err);
        }
    #endif /* CONFIG_BT_NUS_SECURITY_ENABLED */

        err = dk_leds_init();
        if (err) {
            LOG_ERR("Cannot init LEDs (err: %d)", err);
            printk("Cannot init LEDs (err: %d)\n", err);
        }
    }

    void main(void)
    {
        int blink_status = 0;
        int err = 0;
        int8_t txp_get = 0xFF;
        int8_t txp = -30;
        int8_t rssi = 0xFF;

        configure_gpio();

        err = uart_init();
        if (err) {
            error();
        }

        bt_conn_cb_register(&conn_callbacks);

        if (IS_ENABLED(CONFIG_BT_NUS_SECURITY_ENABLED)) {
            bt_conn_auth_cb_register(&conn_auth_callbacks);
        }

        err = bt_enable(NULL);
        if (err) {
            error();
        }
        set_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_ADV,0,txp);

        LOG_INF("Bluetooth initialized");
        printk("Bluetooth initialized\n");

        printk("Get Tx power level ->");
        get_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_ADV, 0, &txp_get);

        k_sem_give(&ble_init_ok);

        if (IS_ENABLED(CONFIG_SETTINGS)) {
            settings_load();
        }

        err = bt_nus_init(&nus_cb);
        if (err) {
            LOG_ERR("Failed to initialize UART service (err: %d)", err);
            printk("Failed to initialize UART service (err: %d)\n", err);
            return;
        }

        err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd,
                      ARRAY_SIZE(sd));
        if (err) {
            LOG_ERR("Advertising failed to start (err %d)", err);
            printk("Advertising failed to start (err %d)\n", err);
            return;
        }
        printk("Get Tx power level ->");
        get_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_ADV, 0, &txp_get);
        printk("-> default TXP = %d\n", txp_get);
        read_conn_rssi(NULL, &rssi);
                printk("RSSI = %d\n", rssi);
        for (;;) {
            dk_set_led(RUN_STATUS_LED, (++blink_status) % 2);
            k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL));
           
            /*ran_data();*/
            const uint8_t sensor_data ='d';
            uint16_t length = 1;
          

            if (bt_nus_send(NULL, &sensor_data, length)) {
           
                LOG_WRN("Failed to send data over BLE connection");
                printk("Failed to send data over BLE connectionl\n");
            }
        }
    }

    void ble_write_thread(void)
    {
        /* Don't go any further until BLE is initialized */
        k_sem_take(&ble_init_ok, K_FOREVER);

        for (;;) {
            /* Wait indefinitely for data to be sent over bluetooth */
            struct uart_data_t *buf = k_fifo_get(&fifo_uart_rx_data,
                                 K_FOREVER);

            //struct uart_user_data *buf ;

            const uint8_t sensor_data ='d';
             uint16_t length = 1;
             

            if (bt_nus_send(NULL, &sensor_data, length)) {
                LOG_WRN("Failed to send data over BLE connection");
                printk("Failed to send data over BLE connectionl\n");
            }

            k_free(buf);
        }
    }

    K_THREAD_DEFINE(ble_write_thread_id, STACKSIZE, ble_write_thread, NULL, NULL,
            NULL, PRIORITY, 0, 0);
    In the end I'm sending a sample data d which is passed to central which i want to time stamp and rssi stamp every time it sends but thats not happening. 
    can you help with that.
    Regards
    Karthik Kumar
Reply
  • Hi,

    I have made these modification on the peripheral uart file which are in red coloured text.


    static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
    {
        ARG_UNUSED(dev);

        static uint8_t *current_buf;
        static size_t aborted_len;
        static bool buf_release;
        struct uart_data_t *buf;
        static uint8_t *aborted_buf;

        switch (evt->type) {
        case UART_TX_DONE:
            LOG_DBG("tx_done");
            printk("tx_done\n");
            if ((evt->data.tx.len == 0) ||
                (!evt->data.tx.buf)) {
                return;
            }

            if (aborted_buf) {
                buf = CONTAINER_OF(aborted_buf, struct uart_data_t,
                           data);
                aborted_buf = NULL;
                aborted_len = 0;
            } else {
                buf = CONTAINER_OF(evt->data.tx.buf, struct uart_data_t,
                           data);
            }

            k_free(buf);

            buf = k_fifo_get(&fifo_uart_tx_data, K_NO_WAIT);
            if (!buf) {
                return;
            }

            if (uart_tx(uart, buf->data, buf->len, SYS_FOREVER_MS)) {
                LOG_WRN("Failed to send data over UART");
                printk("Failed to send data over UART\n");
            }

            break;

        case UART_RX_RDY:
            LOG_DBG("rx_rdy");
            printk("rx_rdy\n");
            buf = CONTAINER_OF(evt->data.rx.buf, struct uart_data_t, data);
            buf->len += evt->data.rx.len;
            buf_release = false;

            if (buf->len == UART_BUF_SIZE) {
                k_fifo_put(&fifo_uart_rx_data, buf);
            } else if ((evt->data.rx.buf[buf->len - 1] == '\n') ||
                  (evt->data.rx.buf[buf->len - 1] == '\r')) {
                k_fifo_put(&fifo_uart_rx_data, buf);
                current_buf = evt->data.rx.buf;
                buf_release = true;
                uart_rx_disable(uart);
            }

            break;

        case UART_RX_DISABLED:
            LOG_DBG("rx_disabled");
            printk("rx_disabled\n");
            buf = k_malloc(sizeof(*buf));
            if (buf) {
                buf->len = 0;
            } else {
                LOG_WRN("Not able to allocate UART receive buffer");
                printk("Not able to allocate UART receive buffer\n");
                k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
                return;
            }

            uart_rx_enable(uart, buf->data, sizeof(buf->data),
                       UART_WAIT_FOR_RX);

            break;

        case UART_RX_BUF_REQUEST:
            LOG_DBG("rx_buf_request");
            printk("rx_buf_request\n");
            buf = k_malloc(sizeof(*buf));
            if (buf) {
                buf->len = 0;
                uart_rx_buf_rsp(uart, buf->data, sizeof(buf->data));
            } else {
                LOG_WRN("Not able to allocate UART receive buffer");
                printk("Not able to allocate UART receive buffer\n");
            }

            break;

        case UART_RX_BUF_RELEASED:
            LOG_DBG("rx_buf_released");
            printk("rx_buf_released\n");
            buf = CONTAINER_OF(evt->data.rx_buf.buf, struct uart_data_t,
                       data);
            if (buf_release && (current_buf != evt->data.rx_buf.buf)) {
                k_free(buf);
                buf_release = false;
                current_buf = NULL;
            }

            break;

        case UART_TX_ABORTED:
                LOG_DBG("tx_aborted");
                printk("tx_aborted\n");
                if (!aborted_buf) {
                    aborted_buf = (uint8_t *)evt->data.tx.buf;
                }

                aborted_len += evt->data.tx.len;
                buf = CONTAINER_OF(aborted_buf, struct uart_data_t,
                           data);

                uart_tx(uart, &buf->data[aborted_len],
                    buf->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->len = 0;
        } else {
            LOG_WRN("Not able to allocate UART receive buffer");
            printk("Not able to allocate UART receive buffer\n");
            k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
            return;
        }

        uart_rx_enable(uart, buf->data, sizeof(buf->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->api;

        return (api->callback_set != NULL);
    }

    static int uart_init(void)
    {
        int err;
        int pos;
        struct uart_data_t *rx;
        struct uart_data_t *tx;

        uart = device_get_binding(CONFIG_BT_NUS_UART_DEV);
        if (!uart) {
            return -ENXIO;
        }

        if (IS_ENABLED(CONFIG_USB_DEVICE_STACK)) {
            err = usb_enable(NULL);
            if (err) {
                LOG_ERR("Failed to enable USB");
                printk("Failed to enable USB\n");
                return err;
            }
        }

        rx = k_malloc(sizeof(*rx));
        if (rx) {
            rx->len = 0;
        } else {
            return -ENOMEM;
        }

        k_work_init_delayable(&uart_work, uart_work_handler);


        if (IS_ENABLED(CONFIG_BT_NUS_UART_ASYNC_ADAPTER) && !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("Cannot initialize UART callback");
            printk("Cannot initialize UART callback\n");
            return err;
        }

        if (IS_ENABLED(CONFIG_UART_LINE_CTRL)) {
            LOG_INF("Wait for DTR");
            printk("Wait for DTR\n");
            while (true) {
                uint32_t dtr = 0;

                uart_line_ctrl_get(uart, UART_LINE_CTRL_DTR, &dtr);
                if (dtr) {
                    break;
                }
                /* Give CPU resources to low priority threads. */
                k_sleep(K_MSEC(100));
            }
            LOG_INF("DTR set");
            printk("DTR set\n");
            err = uart_line_ctrl_set(uart, UART_LINE_CTRL_DCD, 1);
            if (err) {
                LOG_WRN("Failed to set DCD, ret code %d", err);
                printk("Failed to set DCD, ret code %d\n", err);
            }
            err = uart_line_ctrl_set(uart, UART_LINE_CTRL_DSR, 1);
            if (err) {
                LOG_WRN("Failed to set DSR, ret code %d", err);
                printk("Failed to set DSR, ret code %d\n", err);
            }
        }

        tx = k_malloc(sizeof(*tx));

        if (tx) {
            pos = snprintf(tx->data, sizeof(tx->data),
                       "Starting Nordic UART service example\r\n");

            if ((pos < 0) || (pos >= sizeof(tx->data))) {
                k_free(tx);
                LOG_ERR("snprintf returned %d", pos);
                printk("snprintf returned %d\n", pos);
                return -ENOMEM;
            }

            tx->len = pos;
        } else {
            return -ENOMEM;
        }

        err = uart_tx(uart, tx->data, tx->len, SYS_FOREVER_MS);
        if (err) {
            LOG_ERR("Cannot display welcome message (err: %d)", err);
            printk("Cannot display welcome message (err: %d)\n", err);
            return err;
        }

        return uart_rx_enable(uart, rx->data, sizeof(rx->data), 50);
    }
    /*
    Reading RSSI Value
    */
    static void read_conn_rssi(uint16_t handle, int8_t *rssi)
    {
        struct net_buf *buf, *rsp = NULL;
        struct bt_hci_cp_read_rssi *cp;
        struct bt_hci_rp_read_rssi *rp;

        int err;

        buf = bt_hci_cmd_create(BT_HCI_OP_READ_RSSI, sizeof(*cp));
        if (!buf) {
            printk("Unable to allocate command buffer\n");
            return;
        }

        cp = net_buf_add(buf, sizeof(*cp));
        cp->handle = sys_cpu_to_le16(handle);

        err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_RSSI, buf, &rsp);
        if (err) {
            uint8_t reason = rsp ?
                ((struct bt_hci_rp_read_rssi *)rsp->data)->status : 0;
            printk("Read RSSI err: %d reason 0x%02x\n", err, reason);
            return;
        }

        rp = (void *)rsp->data;
        *rssi = rp->rssi;

        net_buf_unref(rsp);
    }
    //uint32_t sd_ble_gap_rssi_start    ( conn_handle, BLE_GAP_EVT_RSSI_CHANGED, BLE_GAP_EVT_RSSI_CHANGED);
    //uint32_t sd_ble_gap_rssi_get  (conn_handle, BLE_GAP_EVT_RSSI_CHANGED, BLE_GAP_EVT_RSSI_CHANGED);
    /* TX Power*/

    static void set_tx_power(uint8_t handle_type, uint16_t handle, int8_t tx_pwr_lvl)
    {
        struct bt_hci_cp_vs_write_tx_power_level *cp;
        struct bt_hci_rp_vs_write_tx_power_level *rp;
        struct net_buf *buf, *rsp = NULL;
        int err;

        buf = bt_hci_cmd_create(BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL,
                    sizeof(*cp));
        if (!buf) {
            printk("Unable to allocate command buffer\n");
            return;
        }

        cp = net_buf_add(buf, sizeof(*cp));
        cp->handle = sys_cpu_to_le16(handle);
        cp->handle_type = handle_type;
        cp->tx_power_level = tx_pwr_lvl;

        err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL,
                       buf, &rsp);
        if (err) {
            uint8_t reason = rsp ?
                ((struct bt_hci_rp_vs_write_tx_power_level *)
                  rsp->data)->status : 0;
            printk("Set Tx power err: %d reason 0x%02x\n", err, reason);
            return;
        }

        rp = (void *)rsp->data;
        printk("Actual Tx Power: %d\n", rp->selected_tx_power);

        net_buf_unref(rsp);
    }


    static void get_tx_power(uint8_t handle_type, uint16_t handle, int8_t *tx_pwr_lvl)
    {
        struct bt_hci_cp_vs_read_tx_power_level *cp;
        struct bt_hci_rp_vs_read_tx_power_level *rp;
        struct net_buf *buf, *rsp = NULL;
        int err;

        *tx_pwr_lvl = 0xFF;
        buf = bt_hci_cmd_create(BT_HCI_OP_VS_READ_TX_POWER_LEVEL,
                    sizeof(*cp));
        if (!buf) {
            printk("Unable to allocate command buffer\n");
            return;
        }

        cp = net_buf_add(buf, sizeof(*cp));
        cp->handle = sys_cpu_to_le16(handle);
        cp->handle_type = handle_type;

        err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_TX_POWER_LEVEL,
                       buf, &rsp);
        if (err) {
            uint8_t reason = rsp ?
                ((struct bt_hci_rp_vs_read_tx_power_level *)
                  rsp->data)->status : 0;
            printk("Read Tx power (Maximum): %d reason 0x%02x\n", err, reason);
            return;
        }

        rp = (void *)rsp->data;
        *tx_pwr_lvl = rp->tx_power_level;

        net_buf_unref(rsp);
    }

    /*connection*/
    static void connected(struct bt_conn *conn, uint8_t conn_err)
    {
        int err;
        int8_t txp;
        struct bt_conn_info info;
        char addr[BT_ADDR_LE_STR_LEN];

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

        if (conn_err) {
            LOG_ERR("Connection failed (err %u)", conn_err);
            printk("Connection failed (err %u)\n", conn_err);
            return;
        }

        /*bt_addr_le_to_str(bt_conn_foreach(conn), addr, sizeof(addr));*/
            err = bt_conn_get_info(conn, &info);

        if (err) {
            printk("Failed to get connection info\n");
        }
         else {
            const struct bt_conn_le_phy_info *phy_info;
            phy_info = BT_CONN_LE_PHY_OPT_CODED_S8;
            get_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_CONN,
                         NULL, &txp);
            LOG_INF("Connected: %s, tx_phy %u, rx_phy %u ,Initial Tx Power = %d",
                   log_strdup(addr), phy_info->tx_phy, phy_info->rx_phy, txp);

            printk("Coded PHY Connected: %s, tx_phy %u, rx_phy %u, Initial Tx Power = %d\n",
                   log_strdup(addr), phy_info->tx_phy, phy_info->rx_phy, txp);
                   //printk(NRF_RADIO->RSSISAMPLE);
                   //uint32_t sd_ble_gap_rssi_start ( conn_handle, 0, 0)
         }

        current_conn = bt_conn_ref(conn);
        /*current_conn = bt_conn_foreach(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));
        /*bt_addr_le_to_str(bt_conn_foreach(conn), addr, sizeof(addr));*/

        LOG_INF("Disconnected: %s (reason %u)", log_strdup(addr), reason);
        printk("Disconnected: %s (reason %u)\n", log_strdup(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("Security changed: %s level %u", log_strdup(addr),
                level);
                printk("Security changed: %s level %u\n", log_strdup(addr),
                level);
        } else {
            LOG_WRN("Security failed: %s level %u err %d", log_strdup(addr),
                level, err);
                printk("Security failed: %s level %u err %d\n", log_strdup(addr),
                level, err);
        }
    }
    #endif

    static struct bt_conn_cb 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("Passkey for %s: %06u", log_strdup(addr), passkey);
        printk("Passkey for %s: %06u\n", log_strdup(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("Passkey for %s: %06u", log_strdup(addr), passkey);
        printk("Passkey for %s: %06u\n", log_strdup(addr), passkey);
        LOG_INF("Press Button 1 to confirm, Button 2 to reject.");
        printk("Press Button 1 to confirm, Button 2 to reject.\n");
    }


    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("Pairing cancelled: %s", log_strdup(addr));
        printk("Pairing cancelled: %s\n", log_strdup(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("Pairing completed: %s, bonded: %d", log_strdup(addr),
            bonded);
            printk("Pairing completed: %s, bonded: %d\n", log_strdup(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("Pairing failed conn: %s, reason %d", log_strdup(addr),
            reason);
            printk("Pairing failed conn: %s, reason %d\n", log_strdup(addr),
            reason);
    }


    static struct bt_conn_auth_cb conn_auth_callbacks = {
        .passkey_display = auth_passkey_display,
        .passkey_confirm = auth_passkey_confirm,
        .cancel = auth_cancel,
        .pairing_complete = pairing_complete,
        .pairing_failed = pairing_failed
    };
    #else
    static struct bt_conn_auth_cb conn_auth_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("Received data from: %s", log_strdup(addr));
        printk("Received data from: %s\n", log_strdup(addr));

        for (uint16_t pos = 0; pos != len;) {
            struct uart_data_t *tx = k_malloc(sizeof(*tx));

            if (!tx) {
                LOG_WRN("Not able to allocate UART send data buffer");
                printk("Not able to allocate UART send data buffer\n");
                return;
            }

            /* Keep the last byte of TX buffer for potential LF char. */
            size_t tx_data_size = sizeof(tx->data) - 1;

            if ((len - pos) > tx_data_size) {
                tx->len = tx_data_size;
            } else {
                tx->len = (len - pos);
            }

            memcpy(tx->data, &data[pos], tx->len);

            pos += tx->len;

            /* Append the LF character when the CR character triggered
             * transmission from the peer.
             */
            if ((pos == len) && (data[len - 1] == '\r')) {
                tx->data[tx->len] = '\n';
                tx->len++;
            }

            err = uart_tx(uart, tx->data, tx->len, SYS_FOREVER_MS);
            if (err) {
                k_fifo_put(&fifo_uart_tx_data, tx);
            }
        }
    }

    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("Numeric Match, conn %p", (void *)auth_conn);
            printk("Numeric Match, conn %p\n", (void *)auth_conn);
        } else {
            bt_conn_auth_cancel(auth_conn);
            LOG_INF("Numeric Reject, conn %p", (void *)auth_conn);
            printk("Numeric Reject, conn %p\n", (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 & has_changed;

        if (auth_conn) {
            if (buttons & KEY_PASSKEY_ACCEPT) {
                num_comp_reply(true);
            }

            if (buttons & 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("Cannot init buttons (err: %d)", err);
            printk("Cannot init buttons (err: %d)\n", err);
        }
    #endif /* CONFIG_BT_NUS_SECURITY_ENABLED */

        err = dk_leds_init();
        if (err) {
            LOG_ERR("Cannot init LEDs (err: %d)", err);
            printk("Cannot init LEDs (err: %d)\n", err);
        }
    }

    void main(void)
    {
        int blink_status = 0;
        int err = 0;
        int8_t txp_get = 0xFF;
        int8_t txp = -30;
        int8_t rssi = 0xFF;

        configure_gpio();

        err = uart_init();
        if (err) {
            error();
        }

        bt_conn_cb_register(&conn_callbacks);

        if (IS_ENABLED(CONFIG_BT_NUS_SECURITY_ENABLED)) {
            bt_conn_auth_cb_register(&conn_auth_callbacks);
        }

        err = bt_enable(NULL);
        if (err) {
            error();
        }
        set_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_ADV,0,txp);

        LOG_INF("Bluetooth initialized");
        printk("Bluetooth initialized\n");

        printk("Get Tx power level ->");
        get_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_ADV, 0, &txp_get);

        k_sem_give(&ble_init_ok);

        if (IS_ENABLED(CONFIG_SETTINGS)) {
            settings_load();
        }

        err = bt_nus_init(&nus_cb);
        if (err) {
            LOG_ERR("Failed to initialize UART service (err: %d)", err);
            printk("Failed to initialize UART service (err: %d)\n", err);
            return;
        }

        err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd,
                      ARRAY_SIZE(sd));
        if (err) {
            LOG_ERR("Advertising failed to start (err %d)", err);
            printk("Advertising failed to start (err %d)\n", err);
            return;
        }
        printk("Get Tx power level ->");
        get_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_ADV, 0, &txp_get);
        printk("-> default TXP = %d\n", txp_get);
        read_conn_rssi(NULL, &rssi);
                printk("RSSI = %d\n", rssi);
        for (;;) {
            dk_set_led(RUN_STATUS_LED, (++blink_status) % 2);
            k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL));
           
            /*ran_data();*/
            const uint8_t sensor_data ='d';
            uint16_t length = 1;
          

            if (bt_nus_send(NULL, &sensor_data, length)) {
           
                LOG_WRN("Failed to send data over BLE connection");
                printk("Failed to send data over BLE connectionl\n");
            }
        }
    }

    void ble_write_thread(void)
    {
        /* Don't go any further until BLE is initialized */
        k_sem_take(&ble_init_ok, K_FOREVER);

        for (;;) {
            /* Wait indefinitely for data to be sent over bluetooth */
            struct uart_data_t *buf = k_fifo_get(&fifo_uart_rx_data,
                                 K_FOREVER);

            //struct uart_user_data *buf ;

            const uint8_t sensor_data ='d';
             uint16_t length = 1;
             

            if (bt_nus_send(NULL, &sensor_data, length)) {
                LOG_WRN("Failed to send data over BLE connection");
                printk("Failed to send data over BLE connectionl\n");
            }

            k_free(buf);
        }
    }

    K_THREAD_DEFINE(ble_write_thread_id, STACKSIZE, ble_write_thread, NULL, NULL,
            NULL, PRIORITY, 0, 0);
    In the end I'm sending a sample data d which is passed to central which i want to time stamp and rssi stamp every time it sends but thats not happening. 
    can you help with that.
    Regards
    Karthik Kumar
Children
Related