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:
- Am I interpreting the results in the transport layer incorrectly?
- 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?
- NETWORK_TRANSMIT_COUNT
- NETWORK_TRANSMIT_INTERVAL_STEPS
- access_publish_period_t publish_period
- step_res
- step_num
- access_publish_retransmit_t publish_retransmit
- count
- interval_steps
- 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