Отправка UDP-пакетов из приложения Android в ESP32 не работает ⇐ Android
-
Гость
Отправка UDP-пакетов из приложения Android в ESP32 не работает
Я создаю приложение для Android, которое должно взаимодействовать с ESP32. Настройка следующая:
[*]ESP32 настраивается как точка доступа [*]ESP32 регулярно отправляет запрос на соединение через широковещательную рассылку UDP. [*]Приложение подключает телефон к Wi-Fi ESP32 (учетные данные на данный момент жестко запрограммированы) [*]Приложение получает запрос на подключение.
Вот где я застрял:
[*]Приложение отвечает отправителю (ESP32) подтверждением. Теперь ESP32 и APP должны знать друг друга.
Я подключился к Wi-Fi на своем ноутбуке и смотрю трафик через WireShark. Все широковещательные сообщения (и многое другое) видны, однако приложение никогда не отправляет UDP-пакеты.
Я совершенно уверен, что сторона ESP32 работает: каждый раз, когда я отправляю udp-пакеты со своего ноутбука через Python, они приходят на ESP. Я настраиваю точку доступа следующим образом:
const IPAddress GateWay(192, 168, 1, 1); const IPAddress localIP (192, 168, 1, 1); const IPAddress подсеть (0, 0, 0, 0); недействительная настройка() { Serial.begin(115200); // sdUtils.begin(); imu.begin(FILTER_UPDATE_RATE_HZ); // настраиваем esp как точку доступа WiFi.softAP(SSID, PASS); //WiFi.config(localIP, GateWay, подсеть); WiFi.softAPConfig(localIP, GateWay, подсеть); Serial.println(udp.begin(2255)); } недействительный цикл() { // инициируем соединение в то время как (!client.connected()) { Serial.println("Инициализация соединения"); // трансляция IP через UDP-трансляцию Строка ipAddress = WiFi.localIP().toString(); udp.beginPacket(WiFi.broadcastIP().toString().c_str(), 2255); udp.println(ipAddress); udp.endPacket(); // анализируем ответ интервал размера пакета; unsigned long startTime = millis(); делать { packageSize = udp.parsePacket(); } while (!packetSize && (millis() - startTime) < 5000); если (размер пакета) { // читаем ответ, который является IP-адресом буфер символов [packetSize]; Serial.println(udp.remoteIP().toString()); udp.read(буфер, packageSize); Строка PhoneIP = буфер; Serial.println(phoneIP); // Устанавливаем TCP-соединение с телефоном client.connect(phoneIP.c_str(), 8080); // Отправляем данные на телефон client.println("Привет от ESP32!"); } еще { Serial.println("Сервер не ответил..."); } } } Вот как я пытаюсь отправить UDP-пакеты в своем приложении для Android:
Связность общедоступного класса { частный конечный контекст контекста; частный WifiManager wifiManager; частный обработчик обработчика; частный сокет DatagramSocket; общедоступное подключение (контекстный контекст) { this.context = контекст; this.handler = новый обработчик(Looper.getMainLooper()); пытаться { wifiManager = (WifiManager) this.context.getSystemService(Context.WIFI_SERVICE); сокет = новый DatagramSocket(2255); Socket.setBroadcast (истина); } catch (IOException e) { Log.e(TAG, «не удалось создать UDP-сокет», e); } } public void ConnectSensor (String ssid, String пароль) { //убедимся, что Wi-Fi включен если (!wifiManager.isWifiEnabled()) { wifiManager.setWifiEnabled(истина); } установитьConAfterQ (ssid, пароль); } общественный недействительный DisconnectSensor () { если (wifiManager.isWifiEnabled()) { wifiManager.disconnect(); wifiManager.setWifiEnabled(ложь); } } общественный недействительный старт () { новый поток(this::receive).start(); } общественная недействительность получения () { в то время как (истина) { буфер байт[] = новый байт[128]; Пакет DatagramPacket = новый DatagramPacket(buffer, buffer.length); пытаться { сокет.получить(пакет); } catch (IOException e) { Log.e(TAG, «Не удалось получить UDP-пакет», e); продолжать; } Строковое сообщение = новая строка (буфер, 0, package.getLength()); Log.d(TAG, "Получен UDP-пакет: " + message.replace("\n", "") + " с IP-адреса: " + package.getAddress().toString() + " в порту: " + package.getPort()); // Отправляем ответ Log.i(TAG, «Отправка ответа»); Строковый ответ = "Эврика, это работает!!"; байтовые данные [] = ответ.getBytes(); Ответ DatagramPacket = новый DatagramPacket(data, data.length, package.getAddress(), package.getPort()); пытаться { сокет.отправить (ответ); } catch (IOException e) { Log.e(TAG, «Не удалось отправить UDP-пакет», e); } } } Функция подключения к Wi-Fi выглядит следующим образом:
private void installConAfterQ(String ssid, String пароль) { Конфигурация WifiEnterpriseConfig = новый WifiEnterpriseConfig(); config.enableTrustOnFirstUse (истина); config.setPassword(пароль); Спецификатор WifiNetworkSpecifier = новый WifiNetworkSpecifier.Builder() .setSsid(ssid) .setWpa2Passphrase(пароль) .строить(); NetworkRequest networkRequest = новый NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .setNetworkSpecifier(спецификатор) .строить(); ConnectivityManager ConnectionManager = (ConnectivityManager) this.context.getSystemService(Context.CONNECTIVITY_SERVICE); // Регистрируем обратный вызов для прослушивания результата соединения ConnectivityManager.NetworkCallback networkCallback = новый ConnectivityManager.NetworkCallback() { @Override public void onAvailable(сеть android.net.Network) { super.onAvailable(сеть); Log.d(TAG, "Подключено к сети Wi-Fi: " + ssid); } @Override общественная недействительность onUnavailable () { супер.onUnavailable(); Log.d(TAG, «Не удалось подключиться к сети Wi-Fi: » + ssid); } }; // Запрашиваем сетевое соединение ConnectionManager.requestNetwork(networkRequest, networkCallback); } Как ни странно, какое-то время все работало хорошо, когда я отключил телефон от компьютера и вручную вошел в точку доступа Wi-Fi. Однако впоследствии я не смог воспроизвести такое поведение.
Мне не хватает чего-то вроде конфигурации соединения, чтобы я не мог отправлять команды UDP? Я довольно тщательно искал в Google, но ничего не нашел.
ОБНОВЛЕНИЕ Я обнаружил, что могу отправлять udp-пакеты с Android на широковещательный адрес (255.255.255.255) или на IP-адрес телефона, на котором установлено приложение. Однако я не могу связаться ни с одним IP-адресом, кроме этих (или, по крайней мере, я его не нашел). Так может быть, в Android встроен скрытый брандмауэр?
Спасибо за любую помощь!
Я создаю приложение для Android, которое должно взаимодействовать с ESP32. Настройка следующая:
[*]ESP32 настраивается как точка доступа [*]ESP32 регулярно отправляет запрос на соединение через широковещательную рассылку UDP. [*]Приложение подключает телефон к Wi-Fi ESP32 (учетные данные на данный момент жестко запрограммированы) [*]Приложение получает запрос на подключение.
Вот где я застрял:
[*]Приложение отвечает отправителю (ESP32) подтверждением. Теперь ESP32 и APP должны знать друг друга.
Я подключился к Wi-Fi на своем ноутбуке и смотрю трафик через WireShark. Все широковещательные сообщения (и многое другое) видны, однако приложение никогда не отправляет UDP-пакеты.
Я совершенно уверен, что сторона ESP32 работает: каждый раз, когда я отправляю udp-пакеты со своего ноутбука через Python, они приходят на ESP. Я настраиваю точку доступа следующим образом:
const IPAddress GateWay(192, 168, 1, 1); const IPAddress localIP (192, 168, 1, 1); const IPAddress подсеть (0, 0, 0, 0); недействительная настройка() { Serial.begin(115200); // sdUtils.begin(); imu.begin(FILTER_UPDATE_RATE_HZ); // настраиваем esp как точку доступа WiFi.softAP(SSID, PASS); //WiFi.config(localIP, GateWay, подсеть); WiFi.softAPConfig(localIP, GateWay, подсеть); Serial.println(udp.begin(2255)); } недействительный цикл() { // инициируем соединение в то время как (!client.connected()) { Serial.println("Инициализация соединения"); // трансляция IP через UDP-трансляцию Строка ipAddress = WiFi.localIP().toString(); udp.beginPacket(WiFi.broadcastIP().toString().c_str(), 2255); udp.println(ipAddress); udp.endPacket(); // анализируем ответ интервал размера пакета; unsigned long startTime = millis(); делать { packageSize = udp.parsePacket(); } while (!packetSize && (millis() - startTime) < 5000); если (размер пакета) { // читаем ответ, который является IP-адресом буфер символов [packetSize]; Serial.println(udp.remoteIP().toString()); udp.read(буфер, packageSize); Строка PhoneIP = буфер; Serial.println(phoneIP); // Устанавливаем TCP-соединение с телефоном client.connect(phoneIP.c_str(), 8080); // Отправляем данные на телефон client.println("Привет от ESP32!"); } еще { Serial.println("Сервер не ответил..."); } } } Вот как я пытаюсь отправить UDP-пакеты в своем приложении для Android:
Связность общедоступного класса { частный конечный контекст контекста; частный WifiManager wifiManager; частный обработчик обработчика; частный сокет DatagramSocket; общедоступное подключение (контекстный контекст) { this.context = контекст; this.handler = новый обработчик(Looper.getMainLooper()); пытаться { wifiManager = (WifiManager) this.context.getSystemService(Context.WIFI_SERVICE); сокет = новый DatagramSocket(2255); Socket.setBroadcast (истина); } catch (IOException e) { Log.e(TAG, «не удалось создать UDP-сокет», e); } } public void ConnectSensor (String ssid, String пароль) { //убедимся, что Wi-Fi включен если (!wifiManager.isWifiEnabled()) { wifiManager.setWifiEnabled(истина); } установитьConAfterQ (ssid, пароль); } общественный недействительный DisconnectSensor () { если (wifiManager.isWifiEnabled()) { wifiManager.disconnect(); wifiManager.setWifiEnabled(ложь); } } общественный недействительный старт () { новый поток(this::receive).start(); } общественная недействительность получения () { в то время как (истина) { буфер байт[] = новый байт[128]; Пакет DatagramPacket = новый DatagramPacket(buffer, buffer.length); пытаться { сокет.получить(пакет); } catch (IOException e) { Log.e(TAG, «Не удалось получить UDP-пакет», e); продолжать; } Строковое сообщение = новая строка (буфер, 0, package.getLength()); Log.d(TAG, "Получен UDP-пакет: " + message.replace("\n", "") + " с IP-адреса: " + package.getAddress().toString() + " в порту: " + package.getPort()); // Отправляем ответ Log.i(TAG, «Отправка ответа»); Строковый ответ = "Эврика, это работает!!"; байтовые данные [] = ответ.getBytes(); Ответ DatagramPacket = новый DatagramPacket(data, data.length, package.getAddress(), package.getPort()); пытаться { сокет.отправить (ответ); } catch (IOException e) { Log.e(TAG, «Не удалось отправить UDP-пакет», e); } } } Функция подключения к Wi-Fi выглядит следующим образом:
private void installConAfterQ(String ssid, String пароль) { Конфигурация WifiEnterpriseConfig = новый WifiEnterpriseConfig(); config.enableTrustOnFirstUse (истина); config.setPassword(пароль); Спецификатор WifiNetworkSpecifier = новый WifiNetworkSpecifier.Builder() .setSsid(ssid) .setWpa2Passphrase(пароль) .строить(); NetworkRequest networkRequest = новый NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .setNetworkSpecifier(спецификатор) .строить(); ConnectivityManager ConnectionManager = (ConnectivityManager) this.context.getSystemService(Context.CONNECTIVITY_SERVICE); // Регистрируем обратный вызов для прослушивания результата соединения ConnectivityManager.NetworkCallback networkCallback = новый ConnectivityManager.NetworkCallback() { @Override public void onAvailable(сеть android.net.Network) { super.onAvailable(сеть); Log.d(TAG, "Подключено к сети Wi-Fi: " + ssid); } @Override общественная недействительность onUnavailable () { супер.onUnavailable(); Log.d(TAG, «Не удалось подключиться к сети Wi-Fi: » + ssid); } }; // Запрашиваем сетевое соединение ConnectionManager.requestNetwork(networkRequest, networkCallback); } Как ни странно, какое-то время все работало хорошо, когда я отключил телефон от компьютера и вручную вошел в точку доступа Wi-Fi. Однако впоследствии я не смог воспроизвести такое поведение.
Мне не хватает чего-то вроде конфигурации соединения, чтобы я не мог отправлять команды UDP? Я довольно тщательно искал в Google, но ничего не нашел.
ОБНОВЛЕНИЕ Я обнаружил, что могу отправлять udp-пакеты с Android на широковещательный адрес (255.255.255.255) или на IP-адрес телефона, на котором установлено приложение. Однако я не могу связаться ни с одним IP-адресом, кроме этих (или, по крайней мере, я его не нашел). Так может быть, в Android встроен скрытый брандмауэр?
Спасибо за любую помощь!
Мобильная версия