I'm building an android app that should talk to an ESP32. The setup is the following:
Here is where I am stuck:
I joined the WiFi with my laptop and watch the traffic via WireShark. All broadcast messages (and lots of other stuff) are visible, however, the APP never sends out an UDP packet.
I am very sure that the ESP32 side works, everytime I send udp packets from my laptop via python, they arrive at the ESP. I setup the Accespoint like this:
const IPAddress gateWay(192, 168, 1, 1);
const IPAddress localIP(192, 168, 1, 1);
const IPAddress subnet(0, 0, 0, 0);
void setup(){
Serial.begin(115200);
// sdUtils.begin();
imu.begin(FILTER_UPDATE_RATE_HZ);
// configure esp as access point
WiFi.softAP(SSID, PASS);
//WiFi.config(localIP, gateWay, subnet);
WiFi.softAPConfig(localIP, gateWay, subnet);
Serial.println(udp.begin(2255));
}
void loop(){
// initiate connection
while (!client.connected()) {
Serial.println("Initializing connection");
// broadcast IP via UDP broadcast
String ipAddress = WiFi.localIP().toString();
udp.beginPacket(WiFi.broadcastIP().toString().c_str(), 2255);
udp.println(ipAddress);
udp.endPacket();
// parse answer
int packetSize;
unsigned long startTime = millis();
do {
packetSize = udp.parsePacket();
} while (!packetSize && (millis() - startTime) < 5000);
if (packetSize) {
// read answer which is IP adress
char buffer[packetSize];
Serial.println(udp.remoteIP().toString());
udp.read(buffer, packetSize);
String phoneIP = buffer;
Serial.println(phoneIP);
// Establish a TCP connection to the phone
client.connect(phoneIP.c_str(), 8080);
// Send data to the phone
client.println("Hello from the ESP32!");
} else {
Serial.println("Server dindn't answer...");
}
}
}
This is how I try to send UDP packages in my android app:
public class Connectivity {
private final Context context;
private WifiManager wifiManager;
private Handler handler;
private DatagramSocket socket;
public Connectivity(Context context) {
this.context = context;
this.handler = new Handler(Looper.getMainLooper());
try {
wifiManager = (WifiManager) this.context.getSystemService(Context.WIFI_SERVICE);
socket = new DatagramSocket(2255);
socket.setBroadcast(true);
} catch (IOException e) {
Log.e(TAG, "failed to create UDP socket", e);
}
}
public void connectSensor(String ssid, String password) {
// make sure wifi is enabled
if (!wifiManager.isWifiEnabled()) {
wifiManager.setWifiEnabled(true);
}
establishConAfterQ(ssid, password);
}
public void disconnectSensor() {
if (wifiManager.isWifiEnabled()) {
wifiManager.disconnect();
wifiManager.setWifiEnabled(false);
}
}
public void start() {
new Thread(this::receive).start();
}
public void receive() {
while (true) {
byte[] buffer = new byte[128];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
try {
socket.receive(packet);
} catch (IOException e) {
Log.e(TAG, "Failed to receive UDP packet", e);
continue;
}
String message = new String(buffer, 0, packet.getLength());
Log.d(TAG, "Received UDP packet: " + message.replace("\n", "") + " from IP address: " + packet.getAddress().toString() + " at port: " + packet.getPort());
// Send the answer
Log.i(TAG, "Sending Answer");
String answer = "Heureka it works!!";
byte[] data = answer.getBytes();
DatagramPacket response = new DatagramPacket(data, data.length, packet.getAddress(), packet.getPort());
try {
socket.send(response);
} catch (IOException e) {
Log.e(TAG, "Failed to send UDP packet", e);
}
}
}
The function where I connect to the wifi looks like the following:
private void establishConAfterQ(String ssid, String password) {
WifiEnterpriseConfig config = new WifiEnterpriseConfig();
config.enableTrustOnFirstUse(true);
config.setPassword(password);
WifiNetworkSpecifier specifier = new WifiNetworkSpecifier.Builder()
.setSsid(ssid)
.setWpa2Passphrase(password)
.build();
NetworkRequest networkRequest = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.setNetworkSpecifier(specifier)
.build();
ConnectivityManager connectivityManager = (ConnectivityManager) this.context.getSystemService(Context.CONNECTIVITY_SERVICE);
// Register a callback to listen for the connection result
ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(android.net.Network network) {
super.onAvailable(network);
Log.d(TAG, "Connected to WiFi network: " + ssid);
}
@Override
public void onUnavailable() {
super.onUnavailable();
Log.d(TAG, "Failed to connect to WiFi network: " + ssid);
}
};
// Request the network connection
connectivityManager.requestNetwork(networkRequest, networkCallback);
}
Weirdly enough, everything worked nicely for a brief time, when I disconnected the phone from the computer and logged into the wifi hotspot manually. However, I could not reproduce this behaviouir thereafter.
Am I missing something like a configuration for the connection so that I cannot send UDP commands? I have searched Google quite intensively, however I haven't found anything.
UPDATE I found out that I can send udp packages from android to the broadcast address (255.255.255.255) or to the IP address of the phone hosting the APP. However, I cannot reach any IP other than those (or at least I haven't found one). So is there maybe a hidden firewall built into android?
Thanks for any help!
There seems no hidden firewall in android.
I use the broadcast, but not to (255.255.255.255).
Just use the localIP from the wifiudp class object, and set the 4th octet to 255, i.e. pertaining only to the current segment.