ESP32 UDP Broadcast Tribulations

As part of my Weather Station upgrade, I am having the ESP communicate status over UDP (like a heartbeat I guess). This will inform me of current sketch version and a few other parameters because it is remote and this would function as a rudimentary ‘Serial Monitor’. I’ll tell yah, I spent about 4 days on this one and it was baffling me. I’ll tell you the steps I took and what finally solved it.

First: I wrote a form-based app in Visual Studio. This essentially was a UDP reader or receiver. The free ‘UDP Sender/Receiver’ on Microsoft Store didn’t work at all unless I was sending or receiving from and to this same PC. I did download this awesome Tool by NagleSoft called ‘Packet Sender’. You can successfully test sending UDP packets to any device or multicast very easily. If I sent packets to this PC using Packet Sender, the UDP Sender/Receiver never worked. However, if I opened my UDP receiver app, the packets and the message string would show like it was supposed to. All well and good. I tried a multitude of scripts that supposedly worked with Arduino to send packets and I couldn’t get any of them to show up on my app, which I know worked. I tried all libraries – the regular Arduino WiFiUDP, an AsyncUDP version, and various combinations of parameters and settings that were supposed to work. I did get hung up for a while on Multicasting, when the simple reality is sending to an IP address in local network that ends with a X.X.X.255 is all you really need. I knew this, but since it wasn’t working on my app, I went down the rabbit hole of Multicast UDP.

Frustration: It didn’t make sense, my app works with a tried and true UDP sending application. I fired up WireShark and I could see the packets and message coming from my ESP32, but they just weren’t reaching my app. Firewall was turned off, but I added a rule to let UDP through anyway. No change. Then I went down the rabbit hole of trying add ARP into the stream…..wasted time. I heard that Windows OS versions like to see this to have network packets behave. Not necessarily. I had experimented on so many parameters and ways to do the same thing, my head was spinning.

Answer: I began to look at this methodically, and look at at all the pieces. OK, WireShark see the packets – so they are being sent through local network successfully. It is a local network, so there is no routing involved. Firewall is not in use. These factors lead me to believe my code on the ESP32 is good and it is doing what it should. So it must be something with my app (even though it works with another UDP sending app). One thing that is frustrating without using threading in my app is the fact it freezes until it get a UDP packet. This is actually how I wanted it, but wondered if that might be affecting how the packet arrives because no other controls or the timer work while it is waiting. Then I thought about something. Even though it seems frozen, it may be just cycling so fast until it gets a packet, that it can’t even get a packet! One thing I omitted was putting in a Time-To-Live statement on the UDPClient method. The reason is, I read or heard somewhere that that is usually just done when you are sending or broadcasting. I added this one line: UDPClient.Ttl = 90 I restarted the app and the packets and data messages started coming through. That is all it was.

The pertinent code for the ESP that worked on my test sketch:

#include <WiFi.h>
#include <WiFiUdp.h>
IPAddress remoteIP(192, 168, 1, 255);
int remotePort = 51888;
char  ReplyBuffer[] = "Data: This and That";
int replyLength;
WiFiUDP Udp;
void setup {
  //Do your wifi connection code here
  replyLength = strlen(ReplyBuffer);
}
void loop {
  Serial.println("Sending…..");
  Udp.beginPacket(remoteIP, remotePort);
  int i = 0;
  for (i=0; i<replyLength;i++)
  {
    Udp.write((uint8_t)ReplyBuffer[i]);
  }
  Udp.endPacket();
  delay(5000);
}