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

Duplicate messages received by mesh server

Hello,

I am developing an application in which mesh client in some cases needs to send consecutive messages to the mesh server. I use a modified version of Simple On/Off model and reliable transfers. 

The problem is that client tries to send second reliable message too quickly after the first. For example, client needs to send some command, receive status from server and then send some data (commands and data are one-packet messages). Mostly it works alright, but once in a while the client tries to send the command again before receiving status from server. Thus, server receives the command, expects to receive data next but in fact it receives the same command again and the message sequence is broken.

I tried unreliable transfer, but too often some messages get lost. Combining unreliable messages with sending them again at a timeout may give the same result (client can send again the message while server is responding to the previous one).

Could you please suggest a proved, trustworthy solution?

  • I am using Mesh SDK v2.2.0

    I put a log into packet_tx function, which is called by access_model_publish, and I could see that sometimes client transmits the message 2 times almost immediately one after another, before receiving the status from the server

    And server replies to both of these messages

  • As you can see in the code snippet belo, the add_reliable_message() function will reschedule an event if a timeout occurs:

    static void add_reliable_message(uint16_t index, const access_reliable_t * p_message)
    {
        NRF_MESH_ASSERT(!m_reliable.pool[index].in_use);
        uint32_t time_now = timer_now();
        memcpy(&(m_reliable.pool[index].params), p_message, sizeof(access_reliable_t));
        m_reliable.pool[index].interval = calculate_interval(p_message);
        m_reliable.pool[index].params.timeout += time_now;
        m_reliable.pool[index].next_timeout = time_now + m_reliable.pool[index].interval;
    
        bearer_event_critical_section_begin();
        if (is_earliest_timeout(index))
        {
            timer_sch_reschedule(&m_reliable.timer, m_reliable.pool[index].next_timeout);
            m_reliable.next_timeout_index = index;
        }
        m_reliable.pool[index].in_use = true;
        m_reliable.active_count++;
        bearer_event_critical_section_end();
    }

    If the server takes a bit too long time to respond with a status message, the client may have reached the timeout & sent another set message.

    You could try changing the min timeout value for an reliable message in the access layer (see access_reliable.h):

    /**
     * Minimum timeout for a reliable message in microseconds.
     * @note Mesh Profile Specification v1.0 recommends this to be minimum 60s.
     */
    #define ACCESS_RELIABLE_TIMEOUT_MIN  (SEC_TO_US(2))
    
    /** Maximum timeout for a reliable message in microseconds. */
    #define ACCESS_RELIABLE_TIMEOUT_MAX  (SEC_TO_US(60))

    It seems the min timeout value used to be 30 seconds in an older mesh sdk version, but I would test out a few values & see if this solves your issue.

  • Thanks a lot! Even though I think server responds in less than 2 seconds, this value is still too small for the needed application.

Related