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

Mesh SAR time-out

Hello everyone.

My project is getting quite complex so I will try to abridge. (Mesh SDK 3.2.0)

I am trying to send wifi credentials from an android application (derived from the Android-nRF-Mesh-Library) to a mesh server node
(said node being connected to an Arduino, it will send the packet over serial for it to establish a connection)
We are currently using nRF52840 DK for both server and client nodes. I have tried using both a config message and generic message but the same problem seems to surface.

If the android device is connected directly to the server, the messages passes without any hurdle. (e.g. upon provisioning the server)
However, if I am connected to a client, the server never gets my mesh packets. (unless the packet is small enough)
Now, I don't want to force my user to connect to the server. If, let's say, the wifi password changed after provisioning happened, as they may have many server nodes, they would need to connect to every single one of them one by one and send the new wifi settings packet.

So on the server, I am getting the first segment in transport.c : trs_seg_packet_in()
but then fires NRF_MESH_EVT_SAR_FAILED with as reason : 0 (NRF_MESH_SAR_CANCEL_REASON_TIMEOUT)

----------

Now, on the client side receiving the mesh packets over proxy, I am of course receiving every segments from the android application.

Inside transport_packet_in(), nrf_mesh_rx_address_get() leads to address_nonvirtual_subscription_exists() in device_state_manager.c
What is weird is that it finds the subscription address but seems to think the subscription count is 0 (even though this very client has been sending app packets to the server subscribing to this address) and then seems to discard the packet.
[EDIT] Ok. This client node is not subscribed to this address so it will drop the packet. Nvm, it all makes sense. I would be glad if anyone could point me where is it it actually relays that packet though. [EDIT 2] Nvm, I found it comes later in network.c : network_packet_in()

I may have done something wrong... :S
Perhaps the server is just not sending confirmation upon receiving a segment?

I am welcoming any help I can get on this Slight smile

  • I found it helpful to increase this value in nrf_mesh_config_core.h :

    #define CORE_TX_QUEUE_BUFFER_SIZE_RELAY 128

    Now (up to 512), the client doesn't give me any "no memory" error anymore.
    However, with max packet data length being 97bytes (9 segments), I still hit SAR time-outs on the server,
    receiving sometimes all 9, but more often seeing only 8 segments or less.
    It is not always the same number dropping either. (ie, sometime only the 3rd one drops, sometime it's another one)

    Reducing size of message to fit in less segments works better...
    but this is not optimal as I cannot realistically know my user's wifi credentials won't be that long.

  • Hi,

    Sorry for the delayed response. Have you had any progress on this matter? Seems like there are some packet loss when sending packets to the server. If I understand this correctly, you hit SAR timeouts on the server when packets are retransmitted from the client?

  • Hi! No worry.
    That's perfectly right.
    Im still stuck on this and I would love to know the cause... Shouldn't the server "ask" for the missing packets?

  • What do you mean by "ask"? A message from the client can be retransmittet a number of times depending on your configuration, to ensure that the server receives this message. An ACK can be sent back from the server if a reliable message was sent. Have you tried increasing the retransmit count on the client? 

  • If it had, let's say, received segment 5 but did not get segment 4... I thought it could fetch it from the message's source.

    I would like to use an acknowledged message for sure. This is a priority as if the server cannot connect to wifi, the rest of the mesh network is pretty much useless.

    From the Nordic Android-nRF-Mesh-Library, I was using sendMeshMessage() of MeshManagerApi.java

    Its name changed in a recent version (2.0.3 ?) to :

    public void createMeshPdu(final int dst, @NonNull final MeshMessage meshMessage)

    but there doesn't seem to be any option to send it as an acknowledged message (nor does it have a retransmission count), or am I mistaken?

    Here's my message, if ever.. :

    public class ServerWifiSet extends GenericMessage {

    private static final String TAG = ServerWifiSet.class.getSimpleName();
    private static final int OP_CODE = ApplicationMessageOpCodes.SERVER_WIFI_SET;

    private final String mSSID;
    private final String mPass;

    /**
    * Constructs PublishServerWifi message.
    *
    * @param appKey application key for this message
    * @param SSID SSID
    * @param pass pass
    * @throws IllegalArgumentException if any illegal arguments are passed
    */
    public PublishServerWifi(@NonNull final ApplicationKey appKey, final String SSID, final String pass) {
    super(appKey);
    if (SSID.length()>32 || pass.length()>64) throw new IllegalArgumentException();
    this.mSSID = SSID;
    this.mPass = pass;
    assembleMessageParameters();
    }

    @Override
    public int getOpCode() {
    return OP_CODE;
    }

    @Override
    void assembleMessageParameters() {
    mAid = SecureUtils.calculateK4(mAppKey.getKey());

    final ByteBuffer paramsBuffer;
    paramsBuffer = ByteBuffer.allocate(this.mSSID.length() + 1 + this.mPass.length()).order(ByteOrder.LITTLE_ENDIAN);
    paramsBuffer.put(this.mSSID.getBytes());
    paramsBuffer.put(new byte[1]); // 1 empty byte for separation
    paramsBuffer.put(this.mPass.getBytes());
    mParameters = paramsBuffer.array();
    //Log.d("Publish mParameters", new String(mParameters));
    }
    }

    Then, again the device connected over proxy seems to receive everything. So should I make this message an acknowledged one only once i got the message on the client side?

Related