facing issue in implementation of NUS service in ble_app_hrs_rscs_relay example

Currently i am trying to implement NUS service in ble_app_hrs_rscs_relay example.

what is i am trying to do:
currently i am use nrf52832 custom board,
nrfSDK version 17.0.2

Segger Embedded studio version 5.64

So, my goal is to made network of relay devices with implementation of NUS service via this service I am able to sending data from UART serial monitor.

What I completed:

To archive this goal first i started from basic data relaying and hopping process for that my network is like
1) ble_app_hrs (heart rate sensor who sending heart rate reading to relay device) ------------ 2) ble_app_hrs_rscs_relay (I connect relay device with hrs peripheral it receives the data from hrs peripheral) ------------ 3) ble_app_hrs_rscs_relay (Connect 6 different relay device to hopping the same data) ------- 4) Mobile Application it receives the data and it's final destination.

I completed and successfully tested this.

Then after sending custom data via  UART 
1) ble_app_uart (it sends the custom data who user given it) ------- 2) Relay Device (ble_app_hrs_rscs_relay  same example with changes) ------- 3) Mobile application (Final destination)

So. in this connection between NUS peripheral device to relay device and relay to mobile application is achieve but facing issue in data sending NUS peripheral device sending data but relay device not able to receives it, also after receive data relaying it is still pending.


log message which shows connection establish successfully; (This log messages are show on Relay Device)

Rec:(10:03:39)<info> app_timer: RTC: initialized.

<info> app: Relay example started. Scanning for NUS peripheral...

<info> app: Relay Node Advertising Started...

<info> app: Found matching device: Nordic_UART, Attempting to connect...

<info> app: Connected to NUS Peripheral (handle: 0)


Rec:(10:04:06)<info> app: Connected to Mobile App (handle: 1)


Here i attach my relay device modify code as well as NUS peripheral device code.

Please guide me via your valuable suggestion.

Thanks in advance.   

//-------------------------------------Relay Device-----------------------------------------
#include "app_timer.h"
#include "app_uart.h"
#include "ble.h"
#include "ble_advdata.h"
#include "ble_advertising.h"
#include "ble_conn_params.h"
#include "ble_conn_state.h"
#include "ble_db_discovery.h"
#include "ble_nus.h"
#include "nrf_ble_gatt.h"
#include "nrf_ble_qwr.h"
#include "nrf_ble_scan.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

#define DEVICE_NAME "Relay_Node" 
#define APP_ADV_INTERVAL 100
#define APP_ADV_DURATION 0
#define APP_BLE_CONN_CFG_TAG 1

NRF_BLE_GATT_DEF(m_gatt);
NRF_BLE_QWR_DEF(m_qwr);
BLE_ADVERTISING_DEF(m_advertising);
NRF_BLE_SCAN_DEF(m_scan);
BLE_NUS_DEF(m_nus, NRF_SDH_BLE_TOTAL_LINK_COUNT);
APP_TIMER_DEF(m_scan_retry_timer);

static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID;
static char nus_rx_data[256];
static char const m_target_periph_name[] = "Nordic_UART";

static uint16_t nus_peripheral_conn_handle = BLE_CONN_HANDLE_INVALID;
static uint16_t mobile_app_conn_handle = BLE_CONN_HANDLE_INVALID;

static void scan_retry_handler(void *p_context) {
    UNUSED_PARAMETER(p_context);
    NRF_LOG_INFO("Retrying scan...");
    scan_start();  // This function is calling nrf_ble_scan_start()
}


static void send_acknowledgment(uint16_t conn_handle) {
    uint8_t ack_data[] = "Data Received";
    uint16_t length = sizeof(ack_data);

    ret_code_t err_code = ble_nus_data_send(&m_nus, ack_data, &length, conn_handle);
    if (err_code == NRF_SUCCESS) {
        NRF_LOG_INFO("Acknowledgment sent to conn_handle: %d", conn_handle);
    } else {
        NRF_LOG_ERROR("Failed to send acknowledgment! Error: %d", err_code);
    }
}

static void relay_nus_data(uint8_t *data, uint16_t length, uint16_t target_conn_handle) {
    if (target_conn_handle == BLE_CONN_HANDLE_INVALID || length == 0) {
        NRF_LOG_WARNING("Invalid connection handle or empty data. Dropping message.");
        return;
    }

    ret_code_t err_code = ble_nus_data_send(&m_nus, data, &length, target_conn_handle);
    if (err_code == NRF_SUCCESS) {
        NRF_LOG_INFO("Data relayed successfully to handle: %d", target_conn_handle);
        send_acknowledgment(target_conn_handle);  // Send acknowledgment after data is relayed
    } else {
        NRF_LOG_ERROR("Failed to relay data! Error: %d", err_code);
    }
}


static void gap_params_init(void) {
    ret_code_t err_code;
    ble_gap_conn_params_t gap_conn_params;
    ble_gap_conn_sec_mode_t sec_mode;

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);

    err_code = sd_ble_gap_device_name_set(&sec_mode,
                                          (const uint8_t *)DEVICE_NAME,
                                          strlen(DEVICE_NAME));
    APP_ERROR_CHECK(err_code);

    memset(&gap_conn_params, 0, sizeof(gap_conn_params));
    gap_conn_params.min_conn_interval = MSEC_TO_UNITS(20, UNIT_1_25_MS);
    gap_conn_params.max_conn_interval = MSEC_TO_UNITS(75, UNIT_1_25_MS);
    gap_conn_params.slave_latency     = 0;
    gap_conn_params.conn_sup_timeout  = MSEC_TO_UNITS(4000, UNIT_10_MS);

    err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
    APP_ERROR_CHECK(err_code);
}

static ble_gap_scan_params_t m_scan_param = {
    .active        = 1,                      // Active scanning
    .interval      = MSEC_TO_UNITS(100, UNIT_0_625_MS),  // 100ms scan interval
    .window        = MSEC_TO_UNITS(50, UNIT_0_625_MS),   // 50ms scan window
    .timeout       = 0,                      // No timeout
    .scan_phys     = BLE_GAP_PHY_1MBPS,      // 1M PHY
    .filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL,
};

static void nus_data_handler(ble_nus_evt_t * p_evt) {
    if (p_evt->type == BLE_NUS_EVT_RX_DATA) {
        NRF_LOG_INFO("Received NUS Data from Peripheral: %s", (char*) p_evt->params.rx_data.p_data);

        // Check source of data and relay to the correct destination
        if (p_evt->conn_handle == nus_peripheral_conn_handle) {
            NRF_LOG_INFO("Forwarding data from NUS Peripheral to Mobile App");
            relay_nus_data(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length, mobile_app_conn_handle);
        } else if (p_evt->conn_handle == mobile_app_conn_handle) {
            NRF_LOG_INFO("Forwarding data from Mobile App to NUS Peripheral");
            relay_nus_data(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length, nus_peripheral_conn_handle);
        } else {
            NRF_LOG_WARNING("Unknown connection handle: %d", p_evt->conn_handle);
        }
    }
}


//@brief Function for initializing the NUS service. */
static void nus_init(void) {
    ret_code_t err_code;
    ble_nus_init_t nus_init;
    nrf_ble_qwr_init_t qwr_init = {0};
    
    qwr_init.error_handler = NULL;
    err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
    APP_ERROR_CHECK(err_code);

    memset(&nus_init, 0, sizeof(nus_init));
    nus_init.data_handler = nus_data_handler;
    err_code = ble_nus_init(&m_nus, &nus_init);
    APP_ERROR_CHECK(err_code);
}

// Make sure the declaration is only static if not intended for external use
void scan_start(void) {
    ret_code_t err_code = nrf_ble_scan_start(&m_scan);
    if (err_code != NRF_SUCCESS) {
        NRF_LOG_ERROR("Scan start failed. Retrying...");
        app_timer_start(m_scan_retry_timer, APP_TIMER_TICKS(5000), NULL); // Retry after 5 sec
    }
}

static void scan_evt_handler(scan_evt_t const *p_scan_evt) {
    ret_code_t err_code;
    ble_gap_evt_adv_report_t const *p_adv = p_scan_evt->params.filter_match.p_adv_report;

    switch (p_scan_evt->scan_evt_id) {
        case NRF_BLE_SCAN_EVT_FILTER_MATCH:
            NRF_LOG_INFO("Found matching device: %s, Attempting to connect...", m_target_periph_name);
            err_code = sd_ble_gap_connect(&p_adv->peer_addr,
                                          &m_scan_param,
                                          &m_scan.conn_params,
                                          APP_BLE_CONN_CFG_TAG);
            APP_ERROR_CHECK(err_code);
            break;
        case NRF_BLE_SCAN_EVT_NOT_FOUND:
            NRF_LOG_INFO("No matching device found.");
            break;
        case NRF_BLE_SCAN_EVT_SCAN_TIMEOUT:
            NRF_LOG_INFO("Scan timed out. Restarting...");
            scan_start();
            break;
        default:
            break;
    }
}

static void advertising_init(void) {
    ret_code_t err_code;
    ble_advertising_init_t init;

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

    // Ensure the device name is included in the advertisement
    init.advdata.name_type          = BLE_ADVDATA_FULL_NAME;
    init.advdata.include_appearance = false;  // Change from true to false (appearance not needed)
    init.advdata.flags              = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;

    // Add manufacturer data or service UUID if needed
    ble_advdata_manuf_data_t manuf_data;
    uint8_t data[] = {0x01, 0x02, 0x03, 0x04};  // Sample manufacturer data
    manuf_data.company_identifier = 0x0059;    // Nordic Semiconductor ID
    manuf_data.data.p_data = data;
    manuf_data.data.size   = sizeof(data);
    init.advdata.p_manuf_specific_data = &manuf_data;

    init.config.ble_adv_fast_enabled  = true;
    init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
    init.config.ble_adv_fast_timeout  = APP_ADV_DURATION;

    err_code = ble_advertising_init(&m_advertising, &init);
    APP_ERROR_CHECK(err_code);

    ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
}

static void advertising_start(void) {
    ret_code_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
    APP_ERROR_CHECK(err_code);
    NRF_LOG_INFO("Relay Node Advertising Started...");
}


static void idle_state_handle(void) {
    if (NRF_LOG_PROCESS() == false) {
        nrf_pwr_mgmt_run();
    }
}


//@brief Function for initializing scanning. */
static void scan_init(void) {
    ret_code_t err_code;
    nrf_ble_scan_init_t init_scan = {0};

    init_scan.p_scan_param = &m_scan_param;  // Ensure the scan parameters are set

    err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_NAME_FILTER, m_target_periph_name);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_ble_scan_filters_enable(&m_scan, NRF_BLE_SCAN_NAME_FILTER, false);
    APP_ERROR_CHECK(err_code);
}


//@brief Function for handling BLE events. */
static void on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) {
    switch (p_ble_evt->header.evt_id) {
        case BLE_GAP_EVT_CONNECTED:
            if (nus_peripheral_conn_handle == BLE_CONN_HANDLE_INVALID) {
                nus_peripheral_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
                NRF_LOG_INFO("Connected to NUS Peripheral (handle: %d)", nus_peripheral_conn_handle);
            } else {
                mobile_app_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
                NRF_LOG_INFO("Connected to Mobile App (handle: %d)", mobile_app_conn_handle);
            }
            break;

        case BLE_GAP_EVT_DISCONNECTED:
            if (p_ble_evt->evt.gap_evt.conn_handle == nus_peripheral_conn_handle) {
                NRF_LOG_WARNING("NUS Peripheral Disconnected.");
                nus_peripheral_conn_handle = BLE_CONN_HANDLE_INVALID;
            } else if (p_ble_evt->evt.gap_evt.conn_handle == mobile_app_conn_handle) {
                NRF_LOG_WARNING("Mobile App Disconnected.");
                mobile_app_conn_handle = BLE_CONN_HANDLE_INVALID;
            }
            break;

        default:
            break;
    }
}

//@brief Function for initializing BLE stack. */
static void ble_stack_init(void) {
    ret_code_t err_code = nrf_sdh_enable_request();
    APP_ERROR_CHECK(err_code);
    uint32_t ram_start = 0;
    err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_sdh_ble_enable(&ram_start);
    APP_ERROR_CHECK(err_code);
    NRF_SDH_BLE_OBSERVER(m_ble_observer, 3, on_ble_evt, NULL);
}

static void log_init(void) {
    ret_code_t err_code = NRF_LOG_INIT(NULL);
    APP_ERROR_CHECK(err_code);
    NRF_LOG_DEFAULT_BACKENDS_INIT();
}

static void gatt_init(void) {
    ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, NULL);
    APP_ERROR_CHECK(err_code);
}


//@brief Function for application main entry. */
int main(void) {
    log_init();
    ble_stack_init();
    gap_params_init();
    gatt_init();
    nus_init();
    scan_init();
    advertising_init();

    // Initialize the scan retry timer
    ret_code_t err_code = app_timer_init();
    APP_ERROR_CHECK(err_code);
    err_code = app_timer_create(&m_scan_retry_timer, APP_TIMER_MODE_SINGLE_SHOT, scan_retry_handler);
    APP_ERROR_CHECK(err_code);

    NRF_LOG_INFO("Relay example started. Scanning for NUS peripheral...");

    advertising_start();
    scan_start();

    for (;;) {
        idle_state_handle();
    }
}


NUS_peripheral

Parents
  • Hi,

    Are you starting development now? If so, I would strongly advice aginst using the nRF5 SDK. The nRF Connect SDK is what we support and what is supported going forward. See nRF Connect SDK and nRF5 SDK statement. Also, nRF5 SDK 17.0.2 does not have support for the latest revision nRF52 series devices (they are supported in nRF5 SDK 17.1.0, though).

  • Hello Einar Thorsrud,

    As i am continue trying to implement NUS service into relay device code and also in HRS peripheral device code, for that i compare my working ble_app_uart peripheral code to relay and hrs peripheral device code.

    In this i implement nus service into ble_hrs_rscs_relay example and in ble_app_hrs example, i am correctly implemented nus service in both example with any error, but now facing issue:
    1) both not advertising and i debug the example then receives this log messages;
    <warning> UARTE: Function: nrfx_uarte_init, error code: NRF_SUCCESS.
    <warning> UARTE: Function: nrfx_uarte_init, error code: NRF_SUCCESS.
    <warning> UARTE: Function: nrfx_uarte_init, error code: NRF_SUCCESS.
    <warning> UARTE: Function: nrfx_uarte_init, error code: NRF_SUCCESS.
    <warning> UARTE: Function: nrfx_uarte_init, error code: NRF_SUCCESS.
    <warning> UARTE: Function: nrfx_uarte_init, error code: NRF_SUCCESS.
    <warning> UARTE: Function: nrfx_uarte_init, error code: NRF_SUCCESS.
    <warning> UARTE: Function: nrfx_uarte_init, error code: NRF_SUCCESS.

    here i attach my main.c file for both relay as well as hrs peripheral device.

    Please verify and guide me as soon as possible.

    Relay


    Peripheral

  • Hi,

    The warning comes from nrfx_err_t nrfx_uarte_init(nrfx_uarte_t const * p_instance() in modules/nrfx/drivers/src/nrfx_uarte.c, and is because you are re-initializing the UART driver. When allready initialized, you get this warning and the init function returns without doing anything more (since it is allready initialized). I do not immeidately see where this is re-initialized though. Perhaps you can set a breakpoint in nrfx_uarte_init in nrfx_uarte.c and check the stack trace to see from where it is called?

    PS: I see you are still usign the nRF5 SDK, so I would like to reiterate that it would be much better to use the nRF Connect SDK and not nRF5 SDK. The nRF5 SDK is old now,  lack important new features,  and will not be updated.

Reply
  • Hi,

    The warning comes from nrfx_err_t nrfx_uarte_init(nrfx_uarte_t const * p_instance() in modules/nrfx/drivers/src/nrfx_uarte.c, and is because you are re-initializing the UART driver. When allready initialized, you get this warning and the init function returns without doing anything more (since it is allready initialized). I do not immeidately see where this is re-initialized though. Perhaps you can set a breakpoint in nrfx_uarte_init in nrfx_uarte.c and check the stack trace to see from where it is called?

    PS: I see you are still usign the nRF5 SDK, so I would like to reiterate that it would be much better to use the nRF Connect SDK and not nRF5 SDK. The nRF5 SDK is old now,  lack important new features,  and will not be updated.

Children
Related