Problems receiving downlinks using the Java API

Hi Guys,

I’m currently working on a project where I have to implement an Application on the server side as well as on the client side. Sometimes the application works as it should but most of the time there are certain difficulties regarding the downlink messages sent from server to client.
In this cases the downlinks are not scheduled as they should and the client receives no data. It is not only that no data is received but the packet forwarder does not even register any kind of downlink. During the next receive window the message which should have been delivered earlier is received. This seems to be a timing problem so that the downlink message is queued and send later on.
But if I compare the timestamps from when the uplink message was sent and the timestamps from when the downlink message was sent it is “only” a difference about half a second. So regarding the default EU setup of 1s and 2s receive delays there should not be any kind of problem.

Is there a point I am missing or does anyone of you has an idea how to fix this?

I’m currently working with a TTN Server and a Java programmed API, as well as a gateway build out of a RPi and an iC880a Concentrator running the packet forwarder software from Semtech and a iM880U as a mote.

I’m looking forward for your help.

What version of the java sdk are you using ?
Could you show us a code sample so that we can try to reproduce ?

In general, downlink messages are queued before the uplink message is sent. This way we don’t have to lose time waiting for an application. Messages have to travel through multiple components, and might come from a gateway halfway across the world, so we need to keep this wait time as low as possible.

We do understand that some applications might require sending an immediate reply, so we allow for a short wait time of 100ms. If your application takes 500ms to respond, the downlink will have missed this window, and will be scheduled for the next opportunity.

To minimize the delay caused by network latency, we recommend to place your application server close to the Handler (Ireland for eu, California for us-west, Sao Paulo for brazil, Singapore for asia-se). To minimize the response time of your application, we recommend to send a response as soon as possible. Many processing steps in your application can be postponed until after sending the downlink back to the network.

Good luck!

Ho, do you think it’s because he tries to give a response directly to an uplink message ?
Btw, it’s why I requested a code sample :slight_smile:

Based on these two quotes, yes:

Thanks for the answers.

I’m using version 1.0.0 due to the circumstances described here.

I’m working from Germany and am using the EU application server but still have a delay of about 500 ms till the data is actually received and processed by the Java API on server side. This may be caused by the size of the data payload which is most of the time about 115 Byte.

This is one shortened part of the application which tends to make problems. I try to respond directly to an uplink message. Is this a problem?

client.onMessage(new BiConsumer<String, Object>() {
		@Override
		public void accept(String _devID, Object _data) {
			System.out.println("Message: " + _devID + " " + _data);
			try {
                JSONObject jobject = (JSONObject) _data;
	        	if (jobject.get("port").equals(49) && !sending) {

					int i, checkCtr;
					Object test = jobject.get("payload_raw");


                    //---------------------------------
                    //some computations with object test
                    //---------------------------------

					// application acks 
					if (i == checkCtr) {
						client.send(_devID, new String("DUPLICATE").getBytes(), 1);				
                        return;
					} else if (i != checkCtr - 1) {
						client.send(_devID, new String("ERROR").getBytes(), 1);
						Arrays.fill(fragData, (byte) 0);
						fragment = false;
						return;
					} else {	
			         	checkCtr = i;
						client.send(_devID,	new String("OK").getBytes(), 1);
             		}

				}  catch (Exception ex) {
				    System.out.println("Response failed: " + ex.getMessage());
			    }
		}
});

Do I need to let the responses get queued first and then send another uplink message which is just intended to receive the last queued downlink before I proceed with the actual application messages?

Couple of observations:

  • A payload of 115 bytes sounds extremely inefficient and is bad practice.
  • Using plaintext ("DUPLICATE", "ERROR", …) is bad practice.

Apart from that, 500ms of processing time is too much for a direct response. Also, keep in mind that you can only send a very limited number of downlink messages per day. You are not working with WiFi or Bluetooth, but are using a technology that is many times more limited. Try to design your application so that it does not need downlink (or as little as possible).

Suggested reading: https://www.thethingsnetwork.org/wiki/LoRaWAN/Limitations

2.1.1 was released a few weeks ago to fix those problems :slight_smile:
Also, performances where greatly improved since 1.x.x that was made for staging :slight_smile: