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

Send high number of messages from one node to another - Mesh SDK 2.1.1

Hi,

I'm trying to use the light_switch example in the Mesh SDK 2.1.1 to build a small experiment to count how many messages are received by the server when sending a consecutive number of messages from the client.

My first approach was to use a function on the client side that consecutively sends a message every 100ms up to a maximum number of messages, using the simple_on_off_client_set_unreliable() like this:

static void send_repeated_message()
{
  for(uint8_t i= 0; i <=10; i++)
  {
    simple_on_off_client_set_unreliable(&m_clients[0], 1, 1);
    nrf_delay_ms(100);
    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Number of message sent: %u\n", i);
  }
}

And on the server side, I modified the on_off_server_set_cb() function to simply count the number of messages received:

static bool on_off_server_set_cb(const simple_on_off_server_t * p_server, bool value)
{
    //__LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Got SET command to %u\n", value);
    //hal_led_pin_set(LED_PIN_NUMBER, value);
    counter += 1;
    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Number of message received: %u\n", counter);
    //return value;
}

And also, I commented the line (void)simple_on_off_server_status_publish(p_server, value); in the handle_set_unreliable_cb(); to avoid sending the server status in reply to the client.

My problem is that in the server side I only see the count of received messages after the client has finished sending ALL the messages and no matter how many messages I send from client, I only receive maximum 5 messages in the server every time!

What could be the reason for this behavior and how to work around this issue?

Thank you in advance!

Regards,
Paulo Zacarias

  • Hi,

    This seems like a strange issue. I haven't seen this before, I'm not sure why you have to wait until all messages are finished sending before seeing the count on the server side. And it shouldn't be a limit on how many messages you can receive on the server. What happens if you send lower than 5 messages?

  • Hi,

    If I send lower than 5 messages the behavior is the same, I only receive the messages in the server after client has finished sending then all.
    It's like messages are store in some kind of buffer before being sent.

    In fact, I changed my code having based my send_repeated_message() function in the simple_on_off_client_set_unreliable() itself instead of calling it every time, so that I call directly access_model_publish() instead:

    static void send_repeated_message()
    {
        uint32_t status = NRF_SUCCESS;
        simple_on_off_client_t * p_client = &m_clients[0];
    
    
        simple_on_off_msg_set_unreliable_t set_unreliable;
        set_unreliable.on_off = 1;
        set_unreliable.tid = m_tid++;
    
        access_message_tx_t message;
        message.opcode.opcode = SIMPLE_ON_OFF_OPCODE_SET_UNRELIABLE;
        message.opcode.company_id = SIMPLE_ON_OFF_COMPANY_ID;
        message.p_buffer = (const uint8_t*) &set_unreliable;
        message.length = sizeof(set_unreliable);
        message.force_segmented = false;
        message.transmic_size = NRF_MESH_TRANSMIC_SIZE_DEFAULT;
    
      for(uint8_t i= 1; i <10; i++)
      {
        message.access_token = nrf_mesh_unique_token_get();
        status = access_model_publish(p_client->model_handle, &message);
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Number of message sent: %u\n", i);
          if (status != NRF_SUCCESS)
          {
             ERROR_CHECK(status);
             break;
             return status;
          }
        nrf_delay_ms(100);
        //__LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Number of message sent: %u\n", i);
      }
    }


    And I found out that the problem is in the client side. It seems to actually store the messages in some sort of buffer or memory and that such buffer can keep only maximum 5 messages, more than that and I receive a NRF_ERROR_NO_MEM:

    <t:     331499>, main.c,  199, Number of message sent: 1
    <t:     334787>, main.c,  199, Number of message sent: 2
    <t:     338074>, main.c,  199, Number of message sent: 3
    <t:     341361>, main.c,  199, Number of message sent: 4
    <t:     344648>, main.c,  199, Number of message sent: 5
    <t:     347930>, main.c,  199, Number of message sent: 6
    <t:     347932>, app_error_weak.c,  105, Mesh error 4 at 0x0002666B (C:\Nordic\nrf5_SDK_for_Mesh_v2.1.1_src_SEND_MESSAGE\examples\light_switch\proxy_client\src\main.c:202)
    

    But how can I figure out were that out of memory comes from?

  • You would need to debug your code to see which function that are returning this error code. I think you might be able to solve this by increasing the RAM.

  • Hi,

    My question was probably not the best , I admit Slight smile

    The thing is that I have been trying already to debug it, but I have some issues.

    I tried to put a break code inside the function access_model_publish() but for some reason I'm not able to set a breakpoint anywhere there:

    Then I tried to look inside the function packet_tx() that is called from the access_model_publish(), but again I'm not able to set a breakpoint there.

    Then I tried to look in the functions called inside packet_tx() to see which one could possibly return the NRF_ERROR_NO_MEM error.

    I found it inside the function access_loopback_handle(), but since I cannot set a breakpoint there either, I cannot say if it's from there that I receive the no memory status:

    But anyway, it would be strange if packet_tx() would call access_loopback_handle(), as from what I understand that function is to verify if destination address is within the node itself, which is not the case...
    But I can't debug there either to be sure:

    I also tried a different approach and set a breakpoint at the app_error_handler() function instead, so I could try to catch what function was return the error, but without success. The function that is shown before the app_error_handler() in the Call Stack is the function I created myself to send the messages:


    So this is from the debug side... On the other hand, don't get it why the messages seem to be "stored" in some kind of  "queue" before being sent, instead of being sent one by one each time we call access_model_publish().

    So even if I increase the RAM somehow,  if I want to send, let's say 50 messages, they will all be stored prior to send? And where in the code is implemented such behavior?

  • The messages will be stored in a buffer, and will be sent out when the Mesh is available. So if you send a lot of messages fast, the buffer will be filled up and you will get NRF_ERROR_NO_MEM.

    I can see that you are using nrf_delay_ms(100); when sending the messages. This can cause a lot of issues and isn't recommended. By using nrf_delay_ms() you will hold up the CPU from doing anything. If you want to use a timer, you can instead use app_timer.

    You can use the tx_complete event to send messages consecutively. That way you won't fill up the buffer.

Related