This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Setting NETWORK_TRANSMIT_COUNT , config_publication_state_t and access_publish_period_t makes no difference!

Hello to all,

(If "TLDR" go to "###TLDR###" in the bottom of the page, where you'll find the straight questions without all the context... )

Me and my team are using the nRF5 SDK 16.0.0_98a08e2 together with nrf5 SDK for Mesh v4.2.0 and the latest S140 softdevice provided in the mentioned SDK to develop for a nRF52840 module.
We developed a BLE mesh system with some vendor models and have a gateway which is also used as a provisioner, following the lines of the provisioner example provided in the Mesh SDK.

One of our models (I'll call it "vendor-model" here) has a server model which sends a message package which is segmented into 4 PDUs, this model can be configured (by the provisioner or hardcoded in the fw) to publish periodically, and with some tweaks in the model configuration we can disable the periodic publication. In any of these cases (with or without periodic publication) I am always catching the message  being received 5 times in the RX node. Let me explain better:

To simplify, during these tests we are using just one RX (client model) and one TX (server model) node, to avoid message relaying and such.
Whenever I send a message (whether via a callback that I invoke using a button via RTT console input which calls app_vendor-model_status_publish(&m_vendor-model_server_0)) or through periodic publication) I always get 5 messages (the original + 4 re-transmissions) in the transport layer, which I probe in transport.c>  transport_packet_in() namely:
- in the TX device I get 5 messages through the p_rx_metadata->source being NRF_MESH_RX_SOURCE_LOOPBACK (obviously)

- in the RX device I get the same 5 messages through p_rx_metadata->source being NRF_MESH_RX_SOURCE_SCANNER

This is a bit puzzling and confusing, because I tested different setting. For instance, in one scenario:

SCENARIO 1:
                #define NETWORK_TRANSMIT_COUNT          (2)
                #define NETWORK_TRANSMIT_INTERVAL_STEPS (1)

         (these were defined in a network_config.h file based on the EXAMPLE_NETWORK_CONFIG_H)

               publish period = 0 ms
               retransmit count = 1
               retransmit steps = 0
               ttl = 10

              these values are printed after the mesh stack is initialized and when provisioned and configured with success. I use the following code to get the values:

access_publish_resolution_t publish_resolution;
    uint8_t publish_step_number;
    access_model_publish_period_get(model_handle, &publish_resolution, &publish_step_number);
    uint32_t publish_period;
    if (publish_resolution == ACCESS_PUBLISH_RESOLUTION_100MS)
        publish_period = publish_step_number * 100;
    else if (publish_resolution == ACCESS_PUBLISH_RESOLUTION_1S)
        publish_period = publish_step_number * 1000;
    else if (publish_resolution == ACCESS_PUBLISH_RESOLUTION_10S)
        publish_period = publish_step_number * 10000;
    else if (publish_resolution == ACCESS_PUBLISH_RESOLUTION_10MIN ||
             publish_resolution == ACCESS_PUBLISH_RESOLUTION_MAX)
        publish_period = publish_step_number * 600000;
    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "publish period = %d ms\n", publish_period);
    nrf_delay_ms(2);

    access_publish_retransmit_t retransmit_params;
    access_model_publish_retransmit_get(model_handle, &retransmit_params);
    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "retransmit count = %d\n", retransmit_params.count);
    nrf_delay_ms(2);
    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "retransmit steps = %d\n", retransmit_params.interval_steps);
    nrf_delay_ms(2);

    uint8_t ttl;
    access_model_publish_ttl_get(model_handle, &ttl);
    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "ttl = %d\n", ttl);
    

             The RX node, acts as a provisioner and configurator. When this occurred, it had the following configuration scenario for this model, as set in node_setup.c > config_step_execute()
(much like in the provisioner example):

      // For TX devices to publish their data every 5 seconds step_num = 5
        case NODE_SETUP_CONFIG_PUBLICATION_VENDOR-MODEL_SERVER_TX:
        {
            access_publish_period_t publish_period =
            {
                .step_num = 0,//Don't publish periodically.step_num = 5,
                .step_res = ACCESS_PUBLISH_RESOLUTION_1S
            };
            config_publication_state_t pubstate = {0};

            status = pub_state_set(&pubstate,
                                   m_current_element_addr,
                                   TX_0_GROUP_ADDRESS,
                                   publish_period);
            __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Setting publication address to 0x%04x for %s on element address 0x%04x\n",
                  TX_0_GROUP_ADDRESS,
                  model_name_by_id_get(mp_config_step->model_id),
                  m_current_element_addr);
            break;
        }

I set the publishing period step_num to 0 to stop periodic publishing to make the debugging clearer and cleaner.

MY AIM: I wanted to do a test where I would only send the message ONCE, but I couldn't set any scenario changing up with these settings that would allow me to do that!

I believe my understanding of this is flawed: With retransmit count = 1 and  #define NETWORK_TRANSMIT_COUNT    (2)  , I would expect the message to be retransmitted twice on the account of the NETWORK_TRANSMIT_COUNT (NTC), and each of those in turn retransmited again due to the retransmit_params.count = 1 (RPC). OK; that would indeed equate to 1 (original message) + 2(NTC)x(1+1(RPC)) = 5 times the message would be sent. However, on the transport.c > upper_transport_tx() in the TX device I get the message being sent TWICE.

In another configuration scenario I used:

SCENARIO 2:

        #define NETWORK_TRANSMIT_COUNT          (0)
        #define NETWORK_TRANSMIT_INTERVAL_STEPS (1)

       publish period = 0 ms
       retransmit count = 1
       retransmit steps = 0
       ttl = 10

The results were the same, sending a message resulted in the original message + 4 re-transmissions, that is, the message is sent 5 times! In this case I was expecting to see only the original message and ONE retransmission, two messages in total!

I couldn't find where to change the retransmit count configuration in the provisioner, so that it could set it up in the provisioned nodes. I know that in config_server.c they are set by:

handle_config_model_publication_set(), in:

access_publish_retransmit_t publish_retransmit;

publish_retransmit.count = p_pubstate->retransmit_count;

publish_retransmit.interval_steps = p_pubstate->retransmit_interval;

and also presumably using the NETWORK_TRANSMIT_COUNT settings in:

handle_config_network_transmit_set(), in:

evt.params.network_transmit_set.retransmit_count = status_message.network_transmit_count;

evt.params.network_transmit_set.interval_steps = status_message.network_transmit_interval


 Unfortunately, I didn't couldn't find a way to tweak the retransmition settings using the provisioner node, because of that I ran a routine I had written before we were using a provisioner, which self-configures the TX node models. That function is called like this:

void setup_model_pub_sub(access_model_handle_t model_handle,
                         uint16_t sub_source_address,
                         uint16_t pub_target_address,
                         uint32_t period_ms,
                         uint8_t retransmit_count,
                         uint8_t retransmit_steps,
                         uint8_t ttl) 

In that function I run the following lines to setup the model publication retransmit:

    access_publish_retransmit_t publish_retransmit;
    publish_retransmit.count = retransmit_count;
    publish_retransmit.interval_steps = retransmit_steps;
    NRF_MESH_ASSERT(
        access_model_publish_retransmit_set(model_handle, publish_retransmit) == NRF_SUCCESS);

SCENARIO 3:

I called my hardcoded self-configuration routine  "setup_model_pub_sub"  with the period_ms, retransmit_count, retransmit_steps and ttl all equal to ZERO. The debug output confirms the model was correctly setup:

       publish period = 0 ms
       retransmit count = 0
       retransmit steps = 0
       ttl = 0

All the while keeping :
        #define NETWORK_TRANSMIT_COUNT          (0)
        #define NETWORK_TRANSMIT_INTERVAL_STEPS (1)

Sending a message resulted in: transport.c > upper_transport_tx()  was called ONCE, which should mean that the message was sent once. However, I got the original message + 4 re-transmissions, that is, the message is sent 5 times! (according to transport.c>  transport_packet_in() ...).  ...

###TLDR###

The problem:

...So my problem is: I got exactly the same results independently of which values I use to configure the retransmit count and network transmit count! My message is always transmitted 5 times according to the transport RX callback I mentioned earlier.

My questions:

  1. Am I interpreting the results in the transport layer incorrectly?
  2. To have a complete reference that might help my esteemed colleagues here in the dev community:  What do the following variables exactly do to the network/model?
    1. NETWORK_TRANSMIT_COUNT
    2. NETWORK_TRANSMIT_INTERVAL_STEPS
    3. access_publish_period_t publish_period
      1. step_res
      2. step_num
    4. access_publish_retransmit_t publish_retransmit
      1. count
      2. interval_steps
  3. How can I correctly setup the  access_publish_retransmit_t publish_retransmit settings for each model, using a device provisioner (like our gateway which we use as a provisioner)?

    We would be most grateful for all insight, information, and answers that could help us solve this irritating issue. Right now it looks like we can't control how many times we have our messages re-transmitted and we're not sure if it is a bug lower in the stack (something on the Nordic SDK) or a shortcoming in our code/understanding. We are optimizing our mesh models since we use some models with rather large message packets occupying too much of the air time (4PDUs x 5 transmissions = 20PDUs for one message! Overkill in this case).

    Thank you very much for your time and effort!

    Best Regards,

    //EA

    • Hi,

      Sorry for the late response.

      I have reached out the team regarding this, will give you an update as soon as I get a response.

    • Thank you Mttrinh! It will be very helpful.
      Best regards!

      //EA

    • Hi,

      1. You send a segmented message with 4 PDUs. The segmentation and reassembly happens at the transport layer. Which means that the whole packet will be split into 4 segments at the transport layer and then will be transferred to the network layer. 

      transport_packet_in() is called by the network layer, when the packet is received. The also happens when the packet is targeted to a group address which the node is subscribed to (by loopback mechanism). I assume that the destination in your scenario is a group address since you say that p_rx_metadata->source is set to NRF_MESH_RX_SOURCE_LOOPBACK.

      There needs to be considered that the network layer has a cache (see msg_cache_entry_exists()), which prevents the message with the same sequence number be processed twice.

      upper_transport_tx() in turn is called before the message being sent by the access layer is segmented by the transport layer.

      Two things needs to be clarified now:

      1. NETWORK_TRANSMIT_COUNT configures number of messages transmissions at the network layer. In other words, how many times a network PDU with the same sequence number will be transmitted.
      2. retransmit_count (called RPC by customer) configures the message publication at the access layer. In other words, how many times an access PDU will be retransmitted.

      So e.g. if you have retransmit_count = 1, you will see the message sent twice in upper_transport_tx(). The first one is the original publication and the second one is the republished message.

      In the mean time, no matter how big NETWORK_TRANSMIT_COUNT value is, if the destination of the message is a group address and the node is subscribed to that address, it will see each network PDU only once in transport_packet_in(). Considering the fact that you send a segmented message, you should see it 4 times (since 4 PDUs). Not sure why you see the message 5 times in transport_packet_in(). Probably, the message is split not to 4, but 5 PDUs. You can add log in transport.c::trs_sar_packet_out() to see how many segments in the message. 

      To the conclusion. To log the incoming and outgoing messages:

      • at the access layer, use mesh_msg_handle() and nrf_mesh_packet_send() (see access.c);
      • at the transport layer, use transport_packet_in() and sar_segment_send() for segmented messages or unsegmented_packet_tx() for unsegmented messages (see transport.c);
      • at the network layer, use network_packet_in() and network_packet_send() (see network.c);

      2.a and 2.b: NETWORK_TRANSMIT_COUNT configures number of transmissions of a network PDU at the network layer while NETWORK_TRANSMIT_INTERVAL_STEPS configures the interval between those transmissions. (see the mesh profile specification v1.0.1, section 4.2.19).

      2.c publish_period configures the interval at which messages are published by a model at the access layer (see the mesh profile specification v1.0.1, section 4.2.2.2).

      2.d publish_retransmit configures retransmissions of the message at the access layer (see the mesh profile specification v1.0.1, section 4.2.2.6, 4.2.2.7).

      3. This depends on your use case. If you wants to see the message once, you need to set publish_rentrasmit and publish_period to 0, and log the incoming message in mesh_msg_handle() in access.c. I also suggest to try out the nRF5 Mesh mobile app. This may also help to clarify how this works.

    • Thank you very much Mttrinh! Your reply was indeed very informative and complete. I still have to perform some tweaks and tests with this new knowledge and will reply when I do so!

      Thank you!

    • Greetings to @all and !

      I finally made it to revisiting this post and looking with more attention to these settings. A few doubts have emerged, and I would be very grateful if you or someone knowledgable could help shed light into the matter.

      1. All messages repeated due to the NETWORK TRANSMIT COUNT should have the same sequence number, therefore other nodes will treat the repetitions as the same message and will discard any replays. Correct?
      2.  Does the NETWORK TRANSMIT COUNT affect all PDUs/messages in the network, including when they are being relayed?
        1. I guess they would be relayed only once since the sequence number is the same for all messages re-transmitted at the network level. That is, if it is set to 2, then the messages will be transmitted 3 times by the source element, and they will always be relayed once by the relaying nodes. Correct?
      3. Another thing I didn't quite understand is: the Re-transmit Count, forces the access layer of the sender element and model instance to send the message 1+Packet Retransmit Count times. However, only the sender gets to do that, right? The relaying nodes forward each repeated message once, but since the original message was re-transmitted with a different SEQ num, they will be treated by the relaying nodes as a different message. correct?
        1. Therefore, each relaying node will forward once each transmitted PDU. Am I wrong?
      4. Finally, What is the sum effect of having both of these variables set? Take the following configuration scenario:
        1. NETWORK TRANSMIT COUNT = 2
          generic_on_off retransmit_count = 2
          Does that mean that each message will be transmited 3 times by the network layer, and 3 times by the access layer, therefore 3x3 = 9 times in total for each PDU!?
      5. Can anyone please point me to a good-practice manual/reference guide for bluetooth mesh tunning!? In my experience a small network has a very different set of needs from a big network (above 10 nodes). I'm losing more packets as the number of nodes grows in the network....

      Thank you very much for making it all the way here! I'm looking forward for all the helpful pointers! If anyone wants to answer partially, please do!

      Best Regards!

    Related