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

Proxy and NUS in one application

Hi,

We are encountering a problem when we try to avail Nordic UART service (NUS) and Mesh service in one application. The problem statement is that after Provisioning, when we disconnect through the nRF Mesh application and go to nRF Connect application to use NUS, we can send only 20 Bytes of data.

But when we dump just the NUS code we availed the service of sending 244 Bytes of data. According to my knowledge there are two main functions in the main.c file of NUS, where the ATT packet size is set after the changes in sdk_config.h.

The first function is the

nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);

2nd function

nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);

 

When I added these functions to the main.c file, I could send 244 Bytes of data, but the nRF Mesh application does not even initialize the connection with the DK and throws an app_error_weak.c.

 

Hence we are not in a position to provision the node and after disconnecting we cannot push 240 Bytes of data via the nRF Connect application.

We are using nRF52840 DK, on SES platform.

Mesh 2.2V along with 15.0.0.

Kind Regards,

Shrinidhi Bhat

Parents
  • Hi, 

    I tried to change MESH_GATT_MTU_SIZE_MAX and NRF_SDH_BLE_GATT_MAX_MTU_SIZE from 69 to 240 in the proxy light switch example in our SDK and has no problem. 

    Please be aware that mesh already has a gatt library (mesh_gatt.c) that handles sd_ble_gatts_exchange_mtu_reply(), you don't need to have nrf_ble_gatt.c library. There should be only one reply to the MTU exchange request. 

    When you see an error, please go into the root cause. 

  • Hi Hung,

    I had done that prior to asking you this question. I had initially set them at 244 and 247 bytes respectively. I even have a log result inside the exchange_mtu_req_handle function which shows the server_rx_mtu size as 247 bytes after the following line of code: 

    uint16_t server_rx_mtu = MAX(MIN(MIN(client_rx_mtu, NRF_SDH_BLE_GATT_MAX_MTU_SIZE), MESH_GATT_MTU_SIZE_MAX), BLE_GATT_ATT_MTU_EDITED); // BLE_GATT_ATT_MTU_EDITED = 247 bytes.

    The problem is when I try to avail the NUS. When I open the nRF Connect application and connect with the DK, it again enters inside the proxy.c and hence mesh_gatt.c as shown by the Log details. Now when I click on NUS and try to send 20 bytes of data, it works perfectly. But when I increase that to 21 bytes, it does not even hit the DK and after some time throws a GATT timeout error (0x85/133).

    I will attach the log file in the sequence of operation as given below:

    1) Connect to the DK via nRF Mesh application (Node is already provisioned before)

    2) Disconnect the node from the nRF Mesh application.

    3) Connect the node via nRF Connect application.

    4) Send 20 Bytes of data using nRF connect app.

    5) Send more than 20 bytes of data.

    NOTE:- I will separate each activity by 3 spaces on the Log file for ease of understanding.

    //This is the Log file and not the code
    //**********1st Activity
    <t:        570>, main.c,  847, Initializing and adding models
    <t:        606>, mesh_gatt.c,  573, Effective MTU Packet size of Mesh_GATT: 244
    <t:        614>, mesh_gatt.c,  556, nus_gatt_peripheral_set: 247
    <t:        631>, main.c, 1075, Device UUID : 005955AA000000004BB1BF73B8371451
    <t:     959866>, main.c,  775, Successfully updated connection parameters
    <t:     959869>, proxy.c,  579, Connected
    <t:     959872>, mesh_gatt.c,  517, Inside connect_evt_handle: 247
    <t:     959874>, mesh_gatt.c,  731, Log inside the mesh_gatt file after BLE_GAP_EVT_CONNECTED
    <t:     996995>, main.c,  775, Successfully updated connection parameters
    <t:     999691>, mesh_gatt.c,  527, Checking this out client: 517
    <t:     999697>, mesh_gatt.c,  531, Checking this out server: 247
    <t:     999701>, mesh_gatt.c,  534, Another Log check: 244
    <t:    1009277>, proxy.c,  605, TX ready
    <t:    1009287>, mesh_gatt.c,  768, Entered here: BLE_GATTS_EVT_WRITE
    <t:    1022062>, mesh_gatt.c,  773, Entered here: BLE_GATTS_EVT_HVN_TX_COMPLETE
    <t:    1022069>, proxy.c,  610, Enters the RX via Mesh gatt Handler
    <t:    1022072>, proxy.c,  553, RX GATT PDU type 0x2, len 19
    <t:    1022083>, mesh_gatt.c,  768, Entered here: BLE_GATTS_EVT_WRITE
    <t:    1028442>, mesh_gatt.c,  773, Entered here: BLE_GATTS_EVT_HVN_TX_COMPLETE
    
    
    
    //**********2nd Activity
    <t:    3498036>, proxy.c,  594, Disconnected
    <t:    3498392>, mesh_gatt.c,  741, Log inside the mesh_gatt file after BLE_GAP_EVT_DISCONNECTED
    
    
    //**********3rd Activity Connect via nRF Connect application
    <t:    4619492>, main.c,  775, Successfully updated connection parameters
    <t:    4619495>, proxy.c,  579, Connected
    <t:    4619497>, mesh_gatt.c,  517, Inside connect_evt_handle: 244
    <t:    4619500>, mesh_gatt.c,  731, Log inside the mesh_gatt file after BLE_GAP_EVT_CONNECTED
    <t:    4658977>, main.c,  775, Successfully updated connection parameters
    
    
    
    //**********4th Activity Send 20 bytes of data via NUS of nRF Connect application
    <t:    8517069>, main.c,  932, The Length of Data received from nRF Connect is 20
    <t:    8517076>, mesh_gatt.c,  768, Entered here: BLE_GATTS_EVT_WRITE
    
    
    //**********5th Activity Send more than 20 bytes of data via NUS of nRF Connect application
    No Log file as nothing is received by the DK. 
    Seeing the Log file of nRF Connect app, there are few takeaways. 
    1--> Writing request to characteristics works fine
    2--> gatt.writeCharacteristic also visible
    3--> Data written to xxxx is NOT visible for anything over 20 bytes
    And after some time GATT timeout error is detected
    
    

    To help debug, I have tried to get as many Logs as possible. Its still not hitting the nus_data_handler function when sending upwards of 20 bytes.

    Awaiting your reply,

    Kind Regards,

    Shrinidhi Bhat

  • Hi Hung,

    My 3rd point does not do the reset part of it.

    my suggestion is to trigger a reset after your finish with  configuration

    Could you please help me out here?

    Currently I haven't called NUS is the main.c file. It is present inside the proxy_init() function itself which is called during the second part of provisioning.

    Should I just add the same inside the initialiaze() function in the main function?

    2 further questions:

    1) Currently I am not able to connect via nRF Toolbox. I have a feeling it is because of the services which do not match. During connection also it hits inside the proxy.c file because of the Mesh_GATT event handler. Am I correct here? Please do let me know where I have gone wrong

    2) But if I want to use the Mesh service again, do we require a reset all over again? Because we cannot have two services parallel right? It can work one after the other.

    How do I go about this?

    I thought that we need send different advertising packets from the node for it to connect via the nRF Toolbox app. Please correct me if I am wrong.

    Kind Regards,

    Shrinidhi Bhat

  • I would suggest you to study BLE and how the softdevice works a little bit more. Try playing with the NUS example.

    Please test using nRF Connect, to check what service you have inside the attribute table. What did you observe when you can't connect using nRFToolbox, do you see the devices in the list ? NRFToolbox should connect to any device, and if it check there is no NUS service it will disconnect. 

    There shouldn't be any problem having multiple services in the GATT table. 

    To trigger a reset you call NVIC_SystemReset()

  • When I open the nRF Connect app, we can see 4 services which include UART_service (Only after Provisioning. Before Provisioning we cannot see the NUS)

    When I try to connect via nRF Toolbox, it disconnects automatically after connection. Checking the log there, I have come to an understanding that:

    The node is giving out Mesh proxy service first. Hence the services do not match and it disconnects. Therefore I cant think of a method to have both the services placed on the same priority level. Meaning, if I want the to avail NUS, it would be ideal to have the Node provisioned first. But I should not be able to use NUS without provisioning.

    Hence after connecting via Mesh_proxy service we are able to use NUS. Now since the services do not match via the nRF Toolbox app, it is disconnecting.

    I'm assuming by your reply that the only way to do this is to Reset the node right?

    I will take a look at it.

    King Regards,

    Shrinidhi Bhat

  • If there is a NUS service in the attribute table, nRFToolbox should keep the connection. Could you find the logging on nRFToolbox ? Could you try to test also with nRFUART app ? 
    When you see an issue, please try to find the root cause, don't use assumption. Why would a reset help here ??

  • I have fixed that particular issue and can connect via the nRF Toolbox application after i disconnect from the Mesh application. But again, disconnecting from the Mesh application does not allow a transfer of more than 20 bytes.

    Here is where you can init your NUS service again.

    I have initialized the NUS inside the proxy_init() function. This is the reason why I can see the extra service added after I provision the device like you mentioned before. Now after Provisioning, I ideally need to disconnect and send the data via the nRF Toolbox application but the major problem now is:

    1) I cannot send more than 20 bytes of data here and have no idea why

    because BLE_NUS_MAX_DATA_LEN has been set to 244 bytes for sure and hence all the characteristics of NUS must reflect the same.

    2) I cannot receive the data from the node because ble_nus_data_send is not working. I have attached the understanding and the points which are not being executed which is resulting the same action.

    // In ble_nus.c inside the function ble_nus_data_send
    if (!p_client->is_notification_enabled)
    {
        return NRF_ERROR_INVALID_STATE; //The error is returning here and hence the data is not being sent over NUS to the mobile application
    }
    
    //Keeping breakpoints we have realised that
    if (ble_srv_is_notification_enabled(p_evt_write->data))
    {
        p_client->is_notification_enabled = true; //This is being executed when we initialize connection via nRFToolbox
        evt.type = BLE_NUS_EVT_COMM_STARTED;
    }
    
    //BUT!!!!! 
    if (p_client->is_notification_enabled)  //Does not enter here
    {
        memset(&evt, 0, sizeof(ble_nus_evt_t));
        evt.type        = BLE_NUS_EVT_TX_RDY;
        evt.p_nus       = p_nus;
        evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
        evt.p_link_ctx  = p_client;
        p_nus->data_handler(&evt);
    }
    
    //I cannot narrow down as to why this is happening

Reply
  • I have fixed that particular issue and can connect via the nRF Toolbox application after i disconnect from the Mesh application. But again, disconnecting from the Mesh application does not allow a transfer of more than 20 bytes.

    Here is where you can init your NUS service again.

    I have initialized the NUS inside the proxy_init() function. This is the reason why I can see the extra service added after I provision the device like you mentioned before. Now after Provisioning, I ideally need to disconnect and send the data via the nRF Toolbox application but the major problem now is:

    1) I cannot send more than 20 bytes of data here and have no idea why

    because BLE_NUS_MAX_DATA_LEN has been set to 244 bytes for sure and hence all the characteristics of NUS must reflect the same.

    2) I cannot receive the data from the node because ble_nus_data_send is not working. I have attached the understanding and the points which are not being executed which is resulting the same action.

    // In ble_nus.c inside the function ble_nus_data_send
    if (!p_client->is_notification_enabled)
    {
        return NRF_ERROR_INVALID_STATE; //The error is returning here and hence the data is not being sent over NUS to the mobile application
    }
    
    //Keeping breakpoints we have realised that
    if (ble_srv_is_notification_enabled(p_evt_write->data))
    {
        p_client->is_notification_enabled = true; //This is being executed when we initialize connection via nRFToolbox
        evt.type = BLE_NUS_EVT_COMM_STARTED;
    }
    
    //BUT!!!!! 
    if (p_client->is_notification_enabled)  //Does not enter here
    {
        memset(&evt, 0, sizeof(ble_nus_evt_t));
        evt.type        = BLE_NUS_EVT_TX_RDY;
        evt.p_nus       = p_nus;
        evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
        evt.p_link_ctx  = p_client;
        p_nus->data_handler(&evt);
    }
    
    //I cannot narrow down as to why this is happening

Children
  • If you don't fully understand how BLE and the NUS service works, it's very hard for us to help you. I strongly suggest you to get to know how NUS works on both the nRF52 side and the Android/iOS side. Try to answer these questions:

    - How does NUS send data from the nRF52 to the phone, using notification or write command ? 

    - How a notification can be enabled for sending (check CCCD)

    - How does the phone send data down to the NRF52,  using notification or write command ? 

    - Try to make your own app to connect to your nRF52, you can refer to the nRF Blinky app. 

Related