Electron: UDP packets loss

Hi,
I've connected my first Electron to the Internet (:raised_hands:) but there are some problem with the connection.
I have an UDP server that can interact with the device.
When the Electron boots up, it can connect to the Particle Cloud in few seconds but it fails to connect to my server.
I've tried with another UDP client and the server can receive requests and respond to them.
So I think that the problem could be on the Electron but the strange thing is that a few times the request sent from the device is received from the server.
The signal received from the device is:

RSSI: -69dBm
Quality: 43dB

Is it good? What could be the problem?
Thanks in advance,

Luca

Donā€™t forget that UDP over wireless can lose dataā€¦ there is no ā€˜resend packetā€™ like with TCP.
Maybe you can move the Electron nearer to the Wifi access point and see if the connection works any better.

1 Like

Electrons is on a cellular connection, though.

1 Like

Oops! sorry - Iā€™ve had Photon in my head all today :slight_smile:

1 Like

Yes, I know that UDP is connectionless and not reliable but Iā€™ve seen that in a test done some years ago, the percentage of success was 100% (only few packets were lost).
Moreover there are a lot of applications that runs over UDP and donā€™t have this problem like DNS, streaming media, VoIP and more specific to this case, also the connection with the Particle Cloud is established over UDPā€¦
And this is the strange thing! With the same protocol the Electron can connect to the Particle Cloud but fails to connect to a nearest server (I suppose because I donā€™t know in which datacenters is running the Particle Cloud)

Does your server accept connections from everything or do you have a firewall and allow specific IPs?

Once thing I have noticed with my AT&T provider is network traffic is routed different depending on which service/port you are using: HTTP(80), HTTPS(443) or SSH(22). So, the inbound IP from the Electron over UDP may not be an IP that you are expecting. IE: The IP address of the Electron may not be the one actually arriving at your server with the UDP packet.

1 Like

Yes the server has a firewall but the port used by the Electron is open and accepts connections from every IP.
If I try with the Photon (with the same firmware) connected to my phoneā€™s hotspot it works (ok, in some rare case a packet is lost but not so often as the Electron).

Yes, it is possible that the IP owned by the device is different from the public IP received by the server because sometimes network providers use NAT/PAT technology with few public IPs because of the lack of IPv4.

Now that is odd.

Is the cell data provider for the Electron the same for your phone's hotspot?

1 Like

No it's different.
But the signal measured by the Electron it's not so bad (or am I wrong?)

Are these values acceptable?

RSSI: -69dBm
Quality: 43dB

@LucaMora, just to be clear, are you having problems connecting to your UDP server or sending data to the server? Could you post your code where you open the server session and send the data?

2 Likes

UDP doesn't establish a connection so when the client is ready, it sends an UDP packet to the server.
Yes, I can post the code but I don't think it could be the problem because I've tested it many times and it works.
I've tried with the Photon and a local server and works perfectly, then with the Photon using my phone's connection and it works but with the Electron on cellular network seems not to work.
The strange thing is that after many attempts a request was received by the server and the device can quickly connect with the Cloud.

void Client::begin(char* ID)
{
unsigned char address[4];
int port;
EEPROM.get(20, address);
EEPROM.get(24, port);

// initialize server
_server.address = address;
_server.port = port;
Serial.print("Server: ");
Serial.print(_server.address);
Serial.printlnf(":%d", _server.port);
_ID = ID;
_client.begin(6543);

}

void Client::hello()
{
Serial.println("Connecting to the server...");

_client.beginPacket(_server.address, _server.port);
_client.write("h");
_client.write(_ID);
_client.endPacket();
unsigned long start = millis();
bool timeout = false;
// wait until server response
while (!timeout && !newMessage()) {
  // if server does not respond cancel attempt
  if ((millis() - start) > 15000) {
    timeout = true;
  }
}
[...]

}

@LucaMora, correct! I should have asked if you could open the UDP port without error. If _client.beginPacket(_server.address, _server.port); returns zero, a socket was not successfully opened. Also _client.endPacket(); will return zero or an error number if the send was unsuccessful. Iā€™m not sure what you do in newMessage() so I canā€™t comment that. You may want to do some error checking to see if you can isolate the issue. The UDP stack is different on the Photon than the Electron so donā€™t expect the same conditions.

3 Likes

Ok, thanks a lot!
I will make some tests to check if the socket can be opened.
The newMessage() is a simple method that returns true if a new message is arrived

bool Client::newMessage()
{
_packetSize = _client.parsePacket();
return (_packetSize > 0) ? true : false;
}

What do you mean with that? There are differences in the implementation or in how they work?
Thanks

@LucaMora, newMessage() looks fine. As for the UDP stacks, the Photonā€™s is based on Cypress WICED coupled with a Broadcom WiFi chip (thus the need for FreeRTOS) while the Electronā€™s uses a UBlox SARA module with a built-in stack and controlled via AT commands. They ā€œdoā€ the same thing but differently.

1 Like

Ok, thanks @peekay123! :+1:
So I only have to try and find where is the problem because client and server seem to be ok :thinking:

@LucaMora, after speaking with @BDub at Particle regarding using SerialLogHandler logHandler(LOG_LEVEL_ALL); in your code to debug the UDP stuff, he indicated:

You should see mdm_hal debugging info with that, which will include UDP AT commands.

Add the command after your #includes and monitor the Serial debug output. You should see your own UDP calls come up in the log stream. Hope it helps! :wink:

1 Like

Also, if you are replying to a UDP packet sent from an Electron, itā€™s very important that you reply to the port the packet came from, not the port that the Electron is listening on.

Wireless carriers used shared IP addresses and port forwarding for cellular devices (including phones), and it sets up temporary port forwarding to return the packet by UDP. If you use the wrong port, the packet wonā€™t make it back to the Electron.

2 Likes

Yes, I know and in fact the server responds immediately to the socket of the received packet.

But the problem is that the request cannot reach the server (according to the logs on the server), so the problem is not in the response.

Also, if you wait longer than 60 seconds to reply, the port route may timeout on the cellular network.

@LucaMora A good test here is to use a simple listener script on the server. If you send from the electron to that server's known IP and open port, it should be received just fine as long as the server does not have something blocking a range of ports.

A nice end to end test which you can be sure to have control over is to find the public IP address for your home internet connection. Log into your WAP and add a route under port forwarding for your local computer's internal IP and PORT range you want open. The electron will definitely be able to hit that IP:PORT as long as you have set it up correctly. Repeat with your server.

###Here's a nice packaged up version of this in a test app I wrote for debugging UDP on the Electron.

:pencil2: IPAddress serverIPaddress( 0,0,0,0 ); // IMPORTANT SET THIS!!!

###Sample output from shorting B0 to GND on electron, and typing messages in terminal to send back:

$ node udp.js 5000
Remote Port (arg 2) not specified, using default: 0
Remote Address (arg 3) not specified, using default: 0.0.0.0
Initialized using remote IP:PORT: 0.0.0.0:0
Listening for UDP packets on 0.0.0.0:5000 ...
received [172.56.20.163:55854(21)] hello from electron 2
received [172.56.20.163:55854(21)] hello from electron 3
received [172.56.20.163:55854(21)] hello from electron 4
hello from server 1
sent [172.56.20.163:55854(19)] hello from server 1
hello from server 2
sent [172.56.20.163:55854(19)] hello from server 2

###Logs from electron:

socketSendTo(0,myhomeipaddress,5000,,21)
    32.212 AT send      35 "AT+USOST=0,\"myhomeipaddress\",5000,21\r\n"
    32.488 AT read  >    3 "\r\n@"
    32.538 AT send      21 "hello from electron 2"
    32.578 AT read  +   16 "\r\n+USOST: 0,21\r\n"
    32.588 AT read OK    6 "\r\nOK\r\n"
0000032589 [app] udp-test-app.cpp:52, callHomeUDP1(): INFO: UDP 1 HELLO SENT

0000033623 [app] udp-test-app.cpp:47, callHomeUDP1(): INFO: UDP 1 HELLO SENDING

socketSendTo(0,myhomeipaddress,5000,,21)
    33.627 AT send      35 "AT+USOST=0,\"myhomeipaddress\",5000,21\r\n"
    33.683 AT read  >    3 "\r\n@"
    33.733 AT send      21 "hello from electron 3"
    33.773 AT read  +   16 "\r\n+USOST: 0,21\r\n"
    33.783 AT read OK    6 "\r\nOK\r\n"
0000033784 [app] udp-test-app.cpp:52, callHomeUDP1(): INFO: UDP 1 HELLO SENT

0000034818 [app] udp-test-app.cpp:47, callHomeUDP1(): INFO: UDP 1 HELLO SENDING

socketSendTo(0,myhomeipaddress,5000,,21)
    34.822 AT send      35 "AT+USOST=0,\"myhomeipaddress\",5000,21\r\n"
    34.868 AT read  >    3 "\r\n@"
    34.918 AT send      21 "hello from electron 4"
    34.958 AT read  +   16 "\r\n+USOST: 0,21\r\n"
    34.968 AT read OK    6 "\r\nOK\r\n"
0000034969 [app] udp-test-app.cpp:52, callHomeUDP1(): INFO: UDP 1 HELLO SENT

    48.752 AT read  +   17 "\r\n+UUSORD: 0,19\r\n"
Socket 0: handle 0 has 19 bytes pending
    48.764 AT send      16 "AT+USORF=0,512\r\n"
    48.804 AT read  +   56 "\r\n+USORF: 0,\"myhomeipaddress\",5000,19,\"hello from server 1\""
    48.816 AT read UNK   2 "\r\n"
    48.826 AT read OK    6 "\r\nOK\r\n"
0000048827 [app] udp-test-app.cpp:75, checkUDP1(): INFO: UDP 1 MESSAGE FROM myhomeipaddress:5000 "hello from server 1"
    55.354 AT read  +   17 "\r\n+UUSORD: 0,19\r\n"
Socket 0: handle 0 has 19 bytes pending
    55.376 AT send      16 "AT+USORF=0,512\r\n"
    55.416 AT read  +   56 "\r\n+USORF: 0,\"myhomeipaddress\",5000,19,\"hello from server 2\""
    55.428 AT read UNK   2 "\r\n"
    55.438 AT read OK    6 "\r\nOK\r\n"
0000055439 [app] udp-test-app.cpp:75, checkUDP1(): INFO: UDP 1 MESSAGE FROM myhomeipaddress:5000 "hello from server 2"
3 Likes

Perfect!
Thank you very much, I will try this piece of code!
Iā€™m sure that the server is well configured because I verified it many times and with other clients works correctly :ok_hand:
As soon as I have time Iā€™ll try all the tests youā€™ve told me to try!
Thanks again :v:

2 Likes