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

How to retrieve Value from multiple Characteristics based Service Handler p_ble_evt->header.evt_id.?

Hi,

 I have one service UUID ffe0 that has two characteristics: one of has UUID ffe4 use for "notify" and other one has UUID ffe5 use for "write and read".

Now i want to get the data from the FFE5 and reply accordingly as per the data that I received from FFE5 suppose I write send data from mobile App to board is "SEND=1" as string to characteristic  UUID FFE5 now according to the message received from the FFE5 service i.e. SEND=1 I want to reflect the characteristic UUID FFE4 as "OK" if the string matches as SEND=1. Now My main Question is How i know when the data is being received from FFE5 characteristic UUID. If I get that as an interrupt or anything I will send a reply as "OK" over the characteristic  UUID FFE4.

I have also created NRF_SDH_BLE_OBSERVER for that service.

But how to get value from the different characteristics UUID like 0xFFE5 and so forth if any .

	switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
                p_our_service->conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
                break;
            case BLE_GAP_EVT_DISCONNECTED:
                p_our_service->conn_handle = BLE_CONN_HANDLE_INVALID;
                break;
            default:
                // No implementation needed.
                break;
        }
        
        


Thanks in advance.

Parents
  • Hello,

    I suggest that you check out the ble_app_uart example, which works pretty much the way that you describe. There is one characteristic for notifications, and one with write (not read).

    Check out how ble_nus.c generates the event BLE_NUS_EVT_RX_DATA from the BLE_GATTS_EVT_WRITE event in ble_nus_on_ble_evt()

    ble_nus_on_ble_evt() is assigned through NRF_SDH_BLE_OBSERVER(), probably like you have done.

    BR,

    Edvin

  • I have made certain changes in the code that you suggested to go through for the quick checking I bypass the app_uart_put that is sending the received data from  Nordic UART BLE Service to UART and instead according to my application I fetch it for my purpose and got trigger for new data as I just wanted for my application explained above and send that received bytes from nus_data_handler over BLE TX Service as Notification.

    As per below code :

    static void nus_data_handler(ble_nus_evt_t * p_evt)
    {
    
        static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
        if (p_evt->type == BLE_NUS_EVT_RX_DATA)
        {
            uint32_t err_code;
    
            NRF_LOG_DEBUG("Received data from BLE NUS. Writing data on UART.");
            NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
    /* Do Not Send to UART 
            for (uint32_t i = 0; i < p_evt->params.rx_data.length; i++)
            {
                do
                {
                    err_code = app_uart_put(p_evt->params.rx_data.p_data[i]);
                    if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY))
                    {
                        NRF_LOG_ERROR("Failed receiving NUS message. Error 0x%x. ", err_code);
                        APP_ERROR_CHECK(err_code);
                    }
                } while (err_code == NRF_ERROR_BUSY);
            }
            if (p_evt->params.rx_data.p_data[p_evt->params.rx_data.length - 1] == '\r')
            {
                while (app_uart_put('\n') == NRF_ERROR_BUSY);
            }
     */
    
    
                do
                {
                    uint16_t length = (uint16_t)p_evt->params.rx_data.length;
                    memcpy(data_array , p_evt->params.rx_data.p_data, length);
                    err_code = ble_nus_data_send(&m_nus, data_array, &length, m_conn_handle);
                    if ((err_code != NRF_ERROR_INVALID_STATE) &&
                        (err_code != NRF_ERROR_RESOURCES) &&
                        (err_code != NRF_ERROR_NOT_FOUND))
                    {
                        APP_ERROR_CHECK(err_code);
                    }
                } while (err_code == NRF_ERROR_RESOURCES);
        }
    
    }



    Is this way correct, as such i am half way instead of bridging the same data i want to analysis the received data from the BLE_NUS_EVT_RX_DATA and then after this I will call ble_nus_data_send .


    Please check the same so that it will get verified from your end also for future use.

    Thanks in advance

  • Looks good!

    One tiny thing you can look into if you want to power optimize your application (minor detail). 

    Your do{} while() loop will make sure that the packet is sent in a proper way. However, if you ever get the NRF_ERROR_RESOURCES return value, you will not allow the chip to go to sleep before it returns NRF_SUCCESS. To further optimize this, you can save the data in some array in your application, leave the event, and then retransmit it on the next BLE_GATTS_EVT_HVN_TX_COMPLETE (you can add this event to your main.c's ble_evt_handler()).

  • OK Thank you for evaluating it,

    I understand your point about the consequences of the do{} while() loop  with NRF_ERROR_RESOURCES,

    But i am still not sure how to implement as you explained in as 

    To further optimize this, you can save the data in some array in your application, leave the event, and then retransmit it on the next BLE_GATTS_EVT_HVN_TX_COMPLETE (you can add this event to your main.c's ble_evt_handler()).

    Can you please explain as in some code snippet of the same thing i want to do as per your technique!

    It would be great help to have !

    And also one thing that i explained is the trigger of the RX characteristics is important to me as to know that data is received too.

  • volatile bool send_flag = false;
    volatile bool more_data = false;
    volatile uint8_t data_array[MAX_LENGTH];
    volatile uint16_t data_length;
    
    
    static void ble_evt_handler(...)
    {
        ...
        case BLE_GATTS_EVT_HVN_TX_COMPLETE:
            if (more_data)
            {
                send_flag = true;
            }
            break;
    }
    
    static void nus_data_handler(ble_nus_evt_t * p_evt)
    {
        ...
        if (p_evt->type == BLE_NUS_EVT_RX_DATA)
        {
            // Copy data from event to your custom data_array.
            for (uint8_t i=0; i<p_evt->....len; i++)
            {
                data_array[i] = p_evt->....data[i];
            }
            data_length = p_evt->...len;
            send_flag = true;
            more_data = true;
        }
    }
    
    
    int main(void)
    {
        // Init everything.
        
        ...
        for(;;)
        {
            if (send_flag)
            {
                send_flag = false;
                err_code = send_data()
                if (err_code == NRF_SUCCESS)
                {
                    
                    more_data = false;
                }
            }
            
            idle_state_handle
        }
    }

    Something like this. Send the data from main, and only try again if the TX_COMPLETE event occurs and you have more data to send.

    BR,
    Edvin

  • Ok thank  for really quick help and I got it ,

    Just to confirm the send_data() would it be as below?:

    uint32_t send_data(void)
    {
        return ble_nus_data_send(&m_nus, data_array, &data_length, m_conn_handle);
    
    }




    Is above send_data() function enough or more preventive code require as far as other nRF flags are concerned ?

  • It worked as you told without NRF_ERROR_RESOURCES as per your suggested code snippet and also above send_data function too.

    Is any other preventive measure to take care of  for final implementation !!!

    Please give suggestion for the same.


    Thank you in advance.





Reply Children
Related