This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Problems while discovering services on a multilink central

Hi,

I developped a multilink central based on the example code ble_app_multilink_central.

I want to connect to several peripherals with two different custom services as shown in the following schematic.

The connection work but I have problems while discovering the services.

Sometimes the central discover all the services but often some services are not discovered and I don't understand why.

The discovery handler executes many times for each connection and the event type is often BLE_DB_DISCOVERY_ERROR.

Here is my discovery handler :

Here is an example of what can happen during a connection with 2 RFID and 1 Relay :

Here we can see that we have the relay on conn_handle 0x0 and the RFIDs on conn_handle 0x1 and 0x2.

We can see that the RFID service is not discovered on the conn_handle 0x1.

My questions are :

-When does the discovery handler execute for each connection?

-How to obtain the event BLE_DB_DISCOVERY_COMPLETE?

-Why does the discovery handler execute several time on each connection? And why is it not executed again while the service is not discovered?

Parents
  • If I remember correctly there is a limitation with the discovery module. so you should only do service discovery on one peer at the time. Can you try to add a check so you do not start service discovery on the new device if the process is already ongoing?

  • Do you have any other suggestions to improve my service discovery please run_ar?

  • How many instances of the DB discovery module have you registered? Could you be using the same for all connections? Check: BLE_DB_DISCOVERY_ARRAY_DEF(m_db_discovery, 2);                      /**< Database discovery module instances. */

    The ble_app_hrs_rscs_relay example has code that shows how to start multiple instances. See the on_ble_central_evt handler in the BLE_GAP_EVT_CONNECTED event.

    If this doesn't help is it possible for you to share your project so I can see what you are doing?

  • Hi,

    I have 4 discovery module instances, 1 relay instance and 3 rfid instance.

    I use "ble_db_discovery_start()" on one instance of the discovery module "&m_db_disc[p_gap_evt->conn_handle]" in the BLE event handler in case BLE_GAP_EVT_CONNECTED (line313).

    This is the main.c of my central :

     

    #include <stdint.h>
    #include <stdio.h>
    #include <string.h>
    #include "nordic_common.h"
    #include "nrf_sdh.h"
    #include "nrf_sdh_ble.h"
    #include "app_timer.h"
    #include "bsp_btn_ble.h"
    #include "ble.h"
    #include "ble_hci.h"
    #include "ble_advdata.h"
    #include "ble_advertising.h"
    #include "ble_conn_params.h"
    #include "ble_db_discovery.h"
    #include "ble_conn_state.h"
    #include "nrf_ble_gatt.h"
    #include "nrf_pwr_mgmt.h"
    
    #include "peer_manager.h"
    #include "fds.h"
    
    #include "rfid_c.h"
    #include "relay_c.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    
    #define APP_BLE_CONN_CFG_TAG      1                                     /**< A tag that refers to the BLE stack configuration we set with @ref sd_ble_cfg_set. Default tag is @ref APP_BLE_CONN_CFG_TAG. */
    #define APP_BLE_OBSERVER_PRIO     3                                     /**< Application's BLE observer priority. You shouldn't need to modify this value. */
    
    #define SEC_PARAM_BOND              1                                   /**< Perform bonding. */
    #define SEC_PARAM_MITM              0                                   /**< Man In The Middle protection not required. */
    #define SEC_PARAM_LESC              0                                   /**< LE Secure Connections not enabled. */
    #define SEC_PARAM_KEYPRESS          0                                   /**< Keypress notifications not enabled. */
    #define SEC_PARAM_IO_CAPABILITIES   BLE_GAP_IO_CAPS_NONE                /**< No I/O capabilities. */
    #define SEC_PARAM_OOB               0                                   /**< Out Of Band data not available. */
    #define SEC_PARAM_MIN_KEY_SIZE      7                                   /**< Minimum encryption key size in octets. */
    #define SEC_PARAM_MAX_KEY_SIZE      16                                  /**< Maximum encryption key size in octets. */
    
    #define CENTRAL_SCANNING_LED      BSP_BOARD_LED_0
    #define CENTRAL_CONNECTED_LED     BSP_BOARD_LED_1
    #define LEDBUTTON_LED             BSP_BOARD_LED_2                       /**< LED to indicate a change of state of the the Button characteristic on the peer. */
    
    #define MEASURE_REQUEST_1_BUTTON     BSP_BUTTON_0//we will not need these buttons for the final version
    #define MEASURE_REQUEST_2_BUTTON     BSP_BUTTON_1
    #define MEASURE_REQUEST_3_BUTTON     BSP_BUTTON_2
    
    #define LEDBUTTON_BUTTON          BSP_BUTTON_0                          /**< Button that will write to the LED characteristic of the peer. */
    #define BUTTON_DETECTION_DELAY    APP_TIMER_TICKS(50)                   /**< Delay from a GPIOTE event until a button is reported as pushed (in number of timer ticks). */
    
    #define SCAN_INTERVAL             0x00A0                                /**< Determines scan interval in units of 0.625 millisecond. */
    #define SCAN_WINDOW               0x00A0                                /**< Determines scan window in units of 0.625 millisecond. */
    #define SCAN_DURATION             0x0000                                /**< Duration of the scanning in units of 10 milliseconds. If set to 0x0000, scanning will continue until it is explicitly disabled. */
    
    #define MIN_CONNECTION_INTERVAL   MSEC_TO_UNITS(99, UNIT_1_25_MS)       /**< Determines minimum connection interval in milliseconds. */
    #define MAX_CONNECTION_INTERVAL   MSEC_TO_UNITS(100, UNIT_1_25_MS)      /**< Determines maximum connection interval in milliseconds. */
    #define SLAVE_LATENCY             0                                     /**< Determines slave latency in terms of connection events. */
    #define SUPERVISION_TIMEOUT       MSEC_TO_UNITS(4000, UNIT_10_MS)       /**< Determines supervision time-out in units of 10 milliseconds. */
    
    #define RFID_COUNT                3                                     //number of relay clients
    #define RELAY_COUNT               1                                     //number of RFID clients
    #define DB_DISC_COUNT             4                                     //number of discovery module, 1 for each peripheral
    
    NRF_BLE_GATT_DEF(m_gatt);                                               /**< GATT module instance. */
    RFID_C_ARRAY_DEF(m_rfid_c, RFID_COUNT);                                 /**< RFID service client instances. */
    RELAY_C_ARRAY_DEF(m_relay_c, RELAY_COUNT);                              /**< RELAY service client instance. */
    BLE_DB_DISCOVERY_ARRAY_DEF(m_db_disc, DB_DISC_COUNT);                   /**< Database discovery module instances. */ 
    
    /**< Name of the devices we try to connect to. These names are searched for in the scan report data*/
    static char const m_target_periph_RFID_name[] = "RFID";             
    static char const m_target_IHMI_relay_name[] = "RELAY";
    
    static uint8_t m_scan_buffer_data[BLE_GAP_SCAN_BUFFER_MIN]; /**< buffer where advertising reports will be stored by the SoftDevice. */
    
    uint8_t cptButtonEvent=0;
    uint8_t measure_request[2]={0xFF,0xFF};
    
    //Pour les UUID custom, faire bien attetntion au quel on a déclaré en premier pour savoir si il s'agit de BEGIN ou BEGIN+1
    ble_uuid_t rfid_uuid = {RFID_UUID, BLE_UUID_TYPE_VENDOR_BEGIN};
    ble_uuid_t relay_uuid = {RELAY_UUID, BLE_UUID_TYPE_VENDOR_BEGIN+1};
    
    /**@brief Pointer to the buffer where advertising reports will be stored by the SoftDevice. */
    static ble_data_t m_scan_buffer =
    {
        m_scan_buffer_data,
        BLE_GAP_SCAN_BUFFER_MIN
    };
    
    /**@brief Scan parameters requested for scanning and connection. */
    static ble_gap_scan_params_t const m_scan_params =
    {
        .active   = 0,
        .interval = SCAN_INTERVAL,
        .window   = SCAN_WINDOW,
    
        .timeout           = SCAN_DURATION,
        .scan_phys         = BLE_GAP_PHY_1MBPS,
        .filter_policy     = BLE_GAP_SCAN_FP_ACCEPT_ALL,
    
    };
    
    /**@brief Connection parameters requested for connection. */
    static ble_gap_conn_params_t const m_connection_param =
    {
        (uint16_t)MIN_CONNECTION_INTERVAL,
        (uint16_t)MAX_CONNECTION_INTERVAL,
        (uint16_t)SLAVE_LATENCY,
        (uint16_t)SUPERVISION_TIMEOUT
    };
    
    static void scan_start(void);
    
    /**@brief Function to handle asserts in the SoftDevice.
     *
     * @details This function will be called in case of an assert in the SoftDevice.
     *
     * @warning This handler is an example only and does not fit a final product. You need to analyze
     *          how your product is supposed to react in case of Assert.
     * @warning On assert from the SoftDevice, the system can only recover on reset.
     *
     * @param[in] line_num     Line number of the failing ASSERT call.
     * @param[in] p_file_name  File name of the failing ASSERT call.
     */
    void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
    {
        app_error_handler(0xDEADBEEF, line_num, p_file_name);
    }
    
    
    /**@brief Function for handling database discovery events.
     *
     * @details This function is callback function to handle events from the database discovery module.
     *          Depending on the UUIDs that are discovered, this function should forward the events
     *          to their respective services.
     *
     * @param[in] p_event  Pointer to the database discovery event.
     */
    static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
    {
        NRF_LOG_INFO("Discovery handler for conn_handle 0x%x\tp_evt->evt-type : %d", p_evt->conn_handle, p_evt->evt_type);
        rfid_on_db_disc_evt(&m_rfid_c[p_evt->conn_handle], p_evt);
        relay_on_db_disc_evt(&m_relay_c[p_evt->conn_handle], p_evt);
    }
    
    
    /**@brief Function for handling Peer Manager events.
     *
     * @param[in] p_evt  Peer Manager event.
     */
    /*
    static void pm_evt_handler(pm_evt_t const * p_evt)
    {
        ret_code_t err_code;
    
        switch (p_evt->evt_id)
        {
            case PM_EVT_BONDED_PEER_CONNECTED:
            {
                NRF_LOG_INFO("Connected to a previously bonded device.");
            } break;
    
            case PM_EVT_CONN_SEC_SUCCEEDED:
            {
                NRF_LOG_INFO("Connection secured: role: %d, conn_handle: 0x%x, procedure: %d.",
                             ble_conn_state_role(p_evt->conn_handle),
                             p_evt->conn_handle,
                             p_evt->params.conn_sec_succeeded.procedure);
            } break;
    
            case PM_EVT_CONN_SEC_FAILED:
            {
    */
                /* Often, when securing fails, it shouldn't be restarted, for security reasons.
                 * Other times, it can be restarted directly.
                 * Sometimes it can be restarted, but only after changing some Security Parameters.
                 * Sometimes, it cannot be restarted until the link is disconnected and reconnected.
                 * Sometimes it is impossible, to secure the link, or the peer device does not support it.
                 * How to handle this error is highly application dependent. */
    /*
            } break;
    
            case PM_EVT_CONN_SEC_CONFIG_REQ:
            {
                // Reject pairing request from an already bonded peer.
                pm_conn_sec_config_t conn_sec_config = {.allow_repairing = false};
                pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config);
            } break;
    
            case PM_EVT_STORAGE_FULL:
            {
                // Run garbage collection on the flash.
                err_code = fds_gc();
                if (err_code == FDS_ERR_NO_SPACE_IN_QUEUES)
                {
                    // Retry.
                }
                else
                {
                    APP_ERROR_CHECK(err_code);
                }
            } break;
    
            case PM_EVT_PEERS_DELETE_SUCCEEDED:
            {
                // Bonds are deleted. Start scanning.
                scan_start();
            } break;
    
            case PM_EVT_PEER_DATA_UPDATE_FAILED:
            {
                // Assert.
                APP_ERROR_CHECK(p_evt->params.peer_data_update_failed.error);
            } break;
    
            case PM_EVT_PEER_DELETE_FAILED:
            {
                // Assert.
                APP_ERROR_CHECK(p_evt->params.peer_delete_failed.error);
            } break;
    
            case PM_EVT_PEERS_DELETE_FAILED:
            {
                // Assert.
                APP_ERROR_CHECK(p_evt->params.peers_delete_failed_evt.error);
            } break;
    
            case PM_EVT_ERROR_UNEXPECTED:
            {
                // Assert.
                APP_ERROR_CHECK(p_evt->params.error_unexpected.error);
            } break;
    
            case PM_EVT_CONN_SEC_START:
            case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED:
            case PM_EVT_PEER_DELETE_SUCCEEDED:
            case PM_EVT_LOCAL_DB_CACHE_APPLIED:
            case PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED:
                // This can happen when the local DB has changed.
            case PM_EVT_SERVICE_CHANGED_IND_SENT:
            case PM_EVT_SERVICE_CHANGED_IND_CONFIRMED:
            default:
                break;
        }
    }
    */
    
    
    /**@brief Function for handling the advertising report BLE event.
     *
     * @param[in] p_adv_report  Advertising report from the SoftDevice.
     */
    static void on_adv_report(ble_gap_evt_adv_report_t const * p_adv_report)
    {
        ret_code_t err_code;
        
        if (ble_advdata_name_find(p_adv_report->data.p_data, p_adv_report->data.len, m_target_periph_RFID_name)&&ble_advdata_uuid_find(p_adv_report->data.p_data, p_adv_report->data.len, &rfid_uuid))
        {//name found
            if(ble_advdata_uuid_find(p_adv_report->data.p_data, p_adv_report->data.len, &rfid_uuid))
            {//custom uuid found
                NRF_LOG_INFO("RFID peripheral found");
                err_code = sd_ble_gap_connect(&p_adv_report->peer_addr, &m_scan_params, &m_connection_param,APP_BLE_CONN_CFG_TAG);
                if (err_code != NRF_SUCCESS)
                {
                    NRF_LOG_ERROR("Connection Request Failed, reason %d", err_code);
                }
            }
        }
        else if(ble_advdata_name_find(p_adv_report->data.p_data, p_adv_report->data.len, m_target_IHMI_relay_name)&&ble_advdata_uuid_find(p_adv_report->data.p_data, p_adv_report->data.len, &relay_uuid))
        {//name found
            if(ble_advdata_uuid_find(p_adv_report->data.p_data, p_adv_report->data.len, &relay_uuid))
            {//custom uuid found
                NRF_LOG_INFO("IHMI relay found");
                err_code = sd_ble_gap_connect(&p_adv_report->peer_addr, &m_scan_params, &m_connection_param,APP_BLE_CONN_CFG_TAG);
                if (err_code != NRF_SUCCESS)
                {
                    NRF_LOG_ERROR("Connection Request Failed, reason %d", err_code);
                }
            }
        }
        else
        {
            //NRF_LOG_INFO("No connection established, scan starts again");
            err_code = sd_ble_gap_scan_start(NULL, &m_scan_buffer);
            APP_ERROR_CHECK(err_code);
        }
    }
    
    
    /**@brief Function for handling BLE events.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     * @param[in]   p_context   Unused.
     */
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        ret_code_t err_code;
    
        // For readability.
        ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;
    
        switch (p_ble_evt->header.evt_id)
        {
            // Upon connection, check which peripheral has connected, initiate DB
            // discovery, update LEDs status and resume scanning if necessary.
            case BLE_GAP_EVT_CONNECTED:
            {
                NRF_LOG_INFO("\tConnection 0x%x established, starting DB discovery.", p_gap_evt->conn_handle);
    
                APP_ERROR_CHECK_BOOL(p_gap_evt->conn_handle < NRF_SDH_BLE_CENTRAL_LINK_COUNT);
    
                err_code = ble_db_discovery_start(&m_db_disc[p_gap_evt->conn_handle], p_gap_evt->conn_handle);
                APP_ERROR_CHECK(err_code);
                if (err_code != NRF_ERROR_BUSY)
                {
                    APP_ERROR_CHECK(err_code);
                }
    
                // Update LEDs status, and check if we should be looking for more
                // peripherals to connect to.
                bsp_board_led_on(CENTRAL_CONNECTED_LED);
    
                /*//il faut attendre que le service soit découvert avant de relancer le start
                if (ble_conn_state_central_conn_count() == NRF_SDH_BLE_CENTRAL_LINK_COUNT)
                {
                    bsp_board_led_off(CENTRAL_SCANNING_LED);
                }
                else
                {
                    // Resume scanning.
                    bsp_board_led_on(CENTRAL_SCANNING_LED);
                    scan_start();
                }
                */
            } break; // BLE_GAP_EVT_CONNECTED
    
            // Upon disconnection, reset the connection handle of the peer which disconnected, update
            // the LEDs status and start scanning again.
            case BLE_GAP_EVT_DISCONNECTED:
            {
                NRF_LOG_INFO("Central link 0x%x disconnected (reason: 0x%x)",
                             p_gap_evt->conn_handle,
                             p_gap_evt->params.disconnected.reason);
    
                if (ble_conn_state_central_conn_count() == 0)
                {
                    // Turn off connection indication LED
                    bsp_board_led_off(CENTRAL_CONNECTED_LED);
                }
    
                // Start scanning
                scan_start();
    
                // Turn on LED for indicating scanning
                bsp_board_led_on(CENTRAL_SCANNING_LED);
    
            } break;
    
            case BLE_GAP_EVT_ADV_REPORT:
                on_adv_report(&p_gap_evt->params.adv_report);
                break;
    
            case BLE_GAP_EVT_TIMEOUT:
            {
                // We have not specified a timeout for scanning, so only connection attemps can timeout.
                if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN)
                {
                    NRF_LOG_INFO("Connection request timed out.");
                }
            } break;
    
            case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
            {
                NRF_LOG_INFO("BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST.");
                // Accept parameters requested by peer.
                err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle,
                                            &p_gap_evt->params.conn_param_update_request.conn_params);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
            {
                NRF_LOG_INFO("PHY update request.");
                ble_gap_phys_t const phys =
                {
                    .rx_phys = BLE_GAP_PHY_AUTO,
                    .tx_phys = BLE_GAP_PHY_AUTO,
                };
                err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GATTC_EVT_TIMEOUT:
            {
                // Disconnect on GATT Client timeout event.
                NRF_LOG_INFO("GATT Client Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GATTS_EVT_TIMEOUT:
            {
                // Disconnect on GATT Server timeout event.
                NRF_LOG_INFO("GATT Server Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
            } break;
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    
    /**@brief Function for initializing the BLE stack.
     *
     * @details Initializes the SoftDevice and the BLE event interrupts.
     */
    static void ble_stack_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        // Configure the BLE stack using the default settings.
        // Fetch the start address of the application RAM.
        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);
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Register a handler for BLE events.
        NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
    }
    
    
    /**@brief Function for the Peer Manager initialization.
     */
    /*
    static void peer_manager_init(void)
    {
        ble_gap_sec_params_t sec_param;
        ret_code_t err_code;
    
        err_code = pm_init();
        APP_ERROR_CHECK(err_code);
    
        memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));
    
        // Security parameters to be used for all security procedures.
        sec_param.bond           = SEC_PARAM_BOND;
        sec_param.mitm           = SEC_PARAM_MITM;
        sec_param.lesc           = SEC_PARAM_LESC;
        sec_param.keypress       = SEC_PARAM_KEYPRESS;
        sec_param.io_caps        = SEC_PARAM_IO_CAPABILITIES;
        sec_param.oob            = SEC_PARAM_OOB;
        sec_param.min_key_size   = SEC_PARAM_MIN_KEY_SIZE;
        sec_param.max_key_size   = SEC_PARAM_MAX_KEY_SIZE;
        sec_param.kdist_own.enc  = 1;
        sec_param.kdist_own.id   = 1;
        sec_param.kdist_peer.enc = 1;
        sec_param.kdist_peer.id  = 1;
    
        err_code = pm_sec_params_set(&sec_param);
        APP_ERROR_CHECK(err_code);
    
        err_code = pm_register(pm_evt_handler);
        APP_ERROR_CHECK(err_code);
    }
    */
    
    
    /** @brief Clear bonding information from persistent storage
     */
    /*
    static void delete_bonds(void)
    {
        ret_code_t err_code;
    
        NRF_LOG_INFO("Erase bonds!");
    
        err_code = pm_peers_delete();
        APP_ERROR_CHECK(err_code);
    }
    */
    
    
    /**@brief Handles events coming from the RFID central module.
     */
    static void rfid_c_evt_handler(rfid_c_t * p_rfid_c, rfid_c_evt_t * p_rfid_c_evt)
    {
        switch (p_rfid_c_evt->evt_type)
        {
            case RFID_C_EVT_DISCOVERY_COMPLETE:
            {
                ret_code_t err_code;
    
                NRF_LOG_INFO("\t\tRFID SERVICE DISCOVERED on conn_handle 0x%x", p_rfid_c_evt->conn_handle);
                
                err_code = rfid_c_handles_assign( p_rfid_c, p_rfid_c_evt->conn_handle, &p_rfid_c_evt->params.peer_db);
                APP_ERROR_CHECK(err_code);
    
                // Initiate bonding.
                /*
                err_code = pm_conn_secure(p_bas_c_evt->conn_handle, false);
                */
              
                //RFID service discovered. Enable notification of sensors_frame.
                err_code = rfid_c_sensors_frame_notif_and_indic_enable(p_rfid_c);
                APP_ERROR_CHECK(err_code);
    
                ///
                if (ble_conn_state_central_conn_count() == NRF_SDH_BLE_CENTRAL_LINK_COUNT)
                {
                    bsp_board_led_off(CENTRAL_SCANNING_LED);
                }
                else
                {
                    // Resume scanning.
                    bsp_board_led_on(CENTRAL_SCANNING_LED);
                    scan_start();
                }
                ///
            
            } break; // BLE_LBS_C_EVT_DISCOVERY_COMPLETE
    
            case RFID_C_EVT_SENSORS_FRAME_RECEIVED:
            {
                //we have to send sensors_frame to the relay
                //it's here that we put functions to execute in case of receiving notifications, not in
                //rfic_c -> BLE_GATTC-EVT_HVX because it can come from another ble service
                      
            } break; // RFID_C_EVT_SENSORS_FRAME_RECEIVED
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    
    /**@brief Handles events coming from the RELAY central module.
     */
    static void relay_c_evt_handler(relay_c_t * p_relay_c, relay_c_evt_t * p_relay_c_evt)
    {
        switch (p_relay_c_evt->evt_type)
        {
            case RELAY_C_EVT_DISCOVERY_COMPLETE:
            {
                ret_code_t err_code;
    
                NRF_LOG_INFO("\t\tRELAY SERVICE DISCOVERED on conn_handle 0x%x", p_relay_c_evt->conn_handle);
    
                err_code = relay_c_handles_assign( p_relay_c, p_relay_c_evt->conn_handle, &p_relay_c_evt->params.peer_db);
                APP_ERROR_CHECK(err_code);
    
                // Initiate bonding.
                /*
                err_code = pm_conn_secure(p_bas_c_evt->conn_handle, false);
                */
                
                //RELAY service discovered. Enable notification of blacklist.
                err_code = relay_c_blacklist_notif_and_indic_enable(p_relay_c);
                APP_ERROR_CHECK(err_code);
    
                ///
                if (ble_conn_state_central_conn_count() == NRF_SDH_BLE_CENTRAL_LINK_COUNT)
                {
                    bsp_board_led_off(CENTRAL_SCANNING_LED);
                }
                else
                {
                    // Resume scanning.
                    bsp_board_led_on(CENTRAL_SCANNING_LED);
                    scan_start();
                }
                ///
    
            } break; // RELAY_C_EVT_DISCOVERY_COMPLETE
    
            case RELAY_C_EVT_BLACKLIST_RECEIVED:
            {
                //we have to save the blacklist
                      
            } break; // RELAY_C_EVT_BLACKLIST_RECEIVED
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    
    /**@brief rfid client initialization.
     */
    static void main_rfid_c_init(void)
    {
        ret_code_t       err_code;
        rfid_c_init_t rfid_c_init_obj;
    
        rfid_c_init_obj.evt_handler = rfid_c_evt_handler;
    
        for (uint32_t i = 0; i < RFID_COUNT; i++)
        {
          err_code = rfid_c_init(&m_rfid_c[i], &rfid_c_init_obj);
          APP_ERROR_CHECK(err_code);
        }
    }
    
    
    /**@brief relay client initialization.
     */
    static void main_relay_c_init(void)
    {
        ret_code_t       err_code;
        relay_c_init_t relay_c_init_obj;
    
        relay_c_init_obj.evt_handler = relay_c_evt_handler;
    
        for (uint32_t i = 0; i < RELAY_COUNT; i++)
        {
            err_code = relay_c_init(&m_relay_c[i], &relay_c_init_obj);
            APP_ERROR_CHECK(err_code);
        }
    }
    
    
    /** @brief Database discovery initialization.
     */
    static void db_discovery_init(void)
    {
        ret_code_t err_code = ble_db_discovery_init(db_disc_handler);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function to start scanning. */
    static void scan_start(void)
    {
        ret_code_t ret;
    
        (void) sd_ble_gap_scan_stop();
    
        NRF_LOG_INFO("Scanning for %s and %s peripherals.", (uint32_t)m_target_periph_RFID_name,(uint32_t)m_target_IHMI_relay_name);
        ret = sd_ble_gap_scan_start(&m_scan_params, &m_scan_buffer);
        APP_ERROR_CHECK(ret);
        // Turn on the LED to signal scanning.
        bsp_board_led_on(CENTRAL_SCANNING_LED);
    }
    
    
    /**@brief Function for initializing power management.
     */
    static void power_management_init(void)
    {
        ret_code_t err_code;
        err_code = nrf_pwr_mgmt_init();
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for handling the idle state (main loop).
     *
     * @details Handle any pending log operation(s), then sleep until the next event occurs.
     */
    static void idle_state_handle(void)
    {
        if (NRF_LOG_PROCESS() == false)
        {
            nrf_pwr_mgmt_run();
        }
    }
    
    
    /**@brief Function for handling events from the button handler module.
     *
     * @param[in] pin_no        The pin that the event applies to.
     * @param[in] button_action The button action (press/release).
     */
    static void button_event_handler(uint8_t pin_no, uint8_t button_action)
    {
        ret_code_t err_code;
    
        switch (pin_no)
        {
            case MEASURE_REQUEST_1_BUTTON:
                cptButtonEvent++;
                if(cptButtonEvent==2)
                {
                  uint8_t measure_request[]={0x1,0x1};
                  for (uint32_t i = 0; i< NRF_SDH_BLE_CENTRAL_LINK_COUNT; i++)
                  {
                      //NRF_LOG_INFO("m_rfid_c[%d].conn_handle : 0x%x",i,m_rfid_c[i].conn_handle);
                      if(m_rfid_c[i].conn_handle != BLE_CONN_HANDLE_INVALID)
                      {
                          write_measure_request(&m_rfid_c[i], measure_request);
                      }
                  }
                  cptButtonEvent=0;
                }
                break;
    
            case MEASURE_REQUEST_2_BUTTON:
                cptButtonEvent++;
                if(cptButtonEvent==2)
                {
                  uint8_t measure_request[]={0x1,0x2};
                  for (uint32_t i = 0; i< NRF_SDH_BLE_CENTRAL_LINK_COUNT; i++)
                  {
                      if(m_rfid_c[i].conn_handle != BLE_CONN_HANDLE_INVALID)
                      {
                          write_measure_request(&m_rfid_c[i], measure_request);
                      }
                  }
                  cptButtonEvent=0;
                }
                break;
    
            case MEASURE_REQUEST_3_BUTTON:
                cptButtonEvent++;
                if(cptButtonEvent==2)
                {
                  uint8_t measure_request[]={0x1,0x3};
                  for (uint32_t i = 0; i< NRF_SDH_BLE_CENTRAL_LINK_COUNT; i++)
                  {
                      if(m_rfid_c[i].conn_handle != BLE_CONN_HANDLE_INVALID)
                      {
                          write_measure_request(&m_rfid_c[i], measure_request);
                      }
                  }
                  cptButtonEvent=0;
                }
                break;
    
            default:
                APP_ERROR_HANDLER(pin_no);
                break;
        }
    }
    
    
    /**@brief Function for initializing the button handler module.
     */
    static void buttons_init(void)
    {
        ret_code_t err_code;
    
        //The array must be static because a pointer to it will be saved in the button handler module.
        static app_button_cfg_t buttons[] =
        {
            {MEASURE_REQUEST_1_BUTTON, false, BUTTON_PULL, button_event_handler},
            {MEASURE_REQUEST_2_BUTTON, false, BUTTON_PULL, button_event_handler},
            {MEASURE_REQUEST_3_BUTTON, false, BUTTON_PULL, button_event_handler}
        };
    
        err_code = app_button_init(buttons, ARRAY_SIZE(buttons),
                                   BUTTON_DETECTION_DELAY);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for the LEDs initialization.
     *
     * @details Initializes all LEDs used by the application.
     */
    static void leds_init(void)
    {
        bsp_board_init(BSP_INIT_LEDS);
    }
    
    
    /** @brief Function for initializing the log module.
     */
    static void log_init(void)
    {
        ret_code_t err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    }
    
    
    /** @brief Function for initializing the timer.
     */
    static void timer_init(void)
    {
        ret_code_t err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for initializing the GATT module.
     */
    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 starting a scan, or instead trigger it from peer manager (after
     *        deleting bonds).
     *
     * @param[in] p_erase_bonds Pointer to a bool to determine if bonds will be deleted before scanning.
     */
    /*
    void scanning_start(bool * p_erase_bonds)
    {
        // Start scanning for peripherals and initiate connection
        // with devices that advertise GATT Service UUID.
        if (*p_erase_bonds == true)
        {
            // Scan is started by the PM_EVT_PEERS_DELETE_SUCCEEDED event.
            delete_bonds();
        }
        else
        {
            scan_start();
        }
    }
    */
    
    
    int main(void)
    {
        ret_code_t err_code;
        bool erase_bonds;
    
        // Initialize.
        log_init();
        NRF_LOG_INFO("------------------------------------------------------------------------------------------");
        NRF_LOG_INFO("-------------------------------------Concentrator-----------------------------------------");
        NRF_LOG_INFO("------------------------------------------------------------------------------------------");
    
        NRF_LOG_INFO("Event types for the discovery :")
        NRF_LOG_INFO("\t%d : BLE_DB_DISCOVERY_COMPLETE",BLE_DB_DISCOVERY_COMPLETE);             
        NRF_LOG_INFO("\t%d : BLE_DB_DISCOVERY_ERROR",BLE_DB_DISCOVERY_ERROR);                   
        NRF_LOG_INFO("\t%d : BLE_DB_DISCOVERY_SRV_NOT_FOUND",BLE_DB_DISCOVERY_SRV_NOT_FOUND);   
        NRF_LOG_INFO("\t%d : BLE_DB_DISCOVERY_AVAILABLE",BLE_DB_DISCOVERY_AVAILABLE);           
    
        timer_init();
        buttons_init();
        leds_init();
        power_management_init();
        ble_stack_init();
        gatt_init();
        db_discovery_init();
        main_rfid_c_init();
        main_relay_c_init();
        ble_conn_state_init();
    
        err_code = app_button_enable();
        APP_ERROR_CHECK(err_code);
    
        //scanning_start(&erase_bonds);
        scan_start();
    
        // Enter main loop.
        for (;;)
        {
           idle_state_handle();
        }
    }

    How can I send you my whole project?

  • Hi,

    Sorry for the late answer. You can create a private ticket and upload your project there.

    Edit: I am afraid I cannot really see what you are doing wrong based on main.c. Have you tried to compare your solution against the nRF5_SDK_15.3.0_59ac345\examples\ble_central_and_peripheral\experimental\ble_app_hrs_rscs_relay example? this example is a client to both HRS and RSCS so it should handle discovery in the same way you application has to do it.

  • Hi, I just created a private ticket with a link to download the whole project.

    I'm going to look at ble_app_hrs_rscs_relay, thank you for the advice.

Reply Children
No Data
Related