Я строю систему с использованием модуля ESP8266 / NodeMcu (похожего на Arduino, только с сетевыми возможностями) и сервера NodeJs, работающего в локальной сети.
Чтобы определить IP-адрес сервера,Я пытаюсь использовать UDP-вещание на модуле NodeMcu.Идея состоит в том, чтобы отправить сообщение на локальный широковещательный IP-адрес (например, 192.168.1.255).Затем сервер получает сообщение и отправляет ответ, подтверждающий, что это сервер.Таким образом, NodeMcu знает прямой адрес сервера для дальнейшей связи.
Проблема в том, что сервер полностью заполняет себя тем же сообщением, когда получает первое сообщение от NodeMcu, тогда как NodeMcuфактически отправляет сообщение только раз в секунду.
На стороне NodeMcu это выглядит так:
[UDP] Sending UDP Broadcast on IP: 192.168.43.255, Port: 8080, Message: ESP8266 UDP Server Discovery Broadcast
Сервер выводит что-то подобное, много раз в секунду:
[10:33:07] 127.0.0.1:8080 @ service discovery : ESP8266 UDP Server Discovery Broadcast
[10:33:07] 127.0.0.1:8080 @ service discovery : ESP8266 UDP Server Discovery Broadcast
[10:33:07] 127.0.0.1:8080 @ service discovery : ESP8266 UDP Server Discovery Broadcast
Не имеет смысла, что он получает столько сообщений, особенно потому, что он явно приходит с 127.0.0.1
, а не с IP-адреса NodeMcu.Он также не отправляет никакого ответа.
Я пытался получить трансляцию на своем телефоне с помощью приложения UDP Monitor , приложения под названием Packet Sender иТерминал Linux.Все работало нормально, и отправка ручного ответа вызвала подтверждение на NodeMcu.
Так что я думаю, что должна быть какая-то ошибка с сервером или с сетью, которую я использую.Сервер работает под управлением Linux на моем компьютере, в то время как я размещаю сеть через точку доступа на моем телефоне (моя настоящая сеть WiFi заблокировала широковещательную передачу по протоколу UDP).Брандмауэр Linux отключен.
Я ни в коем случае не эксперт по JavaScript или NodeJ, и сервер был написан кем-то, с кем я работаю, но он и понятия не имеет.В любом случае, это важная часть на сервере:
client.on('listening', function () {
var address = client.address();
debugMessage(
format('Service discovery running on port %s', config.port)
);
client.setBroadcast(true);
});
client.on('message', function (message, rinfo) {
debugMessage(
format('%s:%s @ service discovery : %s', rinfo.address, rinfo.port, message)
);
client.send(message, 0, message.length, rinfo.port, rinfo.ip);
});
client.bind(config.port);
Код на NodeMcu выглядит следующим образом:
#include <ESP8266WiFi.h> // WiFi library
#include <WiFiUdp.h> // UPD functionality
// UDP variables
WiFiUDP udp;
unsigned int localUdpPort = 8080;
char incomingPacket[255];
const char broadcastMessage[] = "ESP8266 UDP Server Discovery Broadcast";
// Server details - written to when the server is found
IPAddress serverIp = ~WiFi.subnetMask() | WiFi.gatewayIP(); // Use Broadcast Address as default in case the UDP service discovery isn't working as intended
unsigned int serverPort = localUdpPort; // Use local port as default in case the UDP service discovery ins't working as intended
void setupWiFi()
{
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
#if LOGGING
Serial.println("Connecting to network: " + (String) WIFI_SSID);
#endif
while (WiFi.status() != WL_CONNECTED)
{
delay(100);
}
#if LOGGING
Serial.print("Connected to network, Local IP Address: ");
Serial.println(WiFi.localIP());
#endif
udp.begin(localUdpPort); // begin listening on UDP port
#if LOGGING
Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localUdpPort);
#endif LOGGING
}
// Discover the server via a UDP broadcast, and store it's IP and Port in the local network in field variables for later use
// IMPORTANT - For the server to work, the Linux Firewall has to be disabled!!!
void discoverServer()
{
changeColor(PURPLE, false); // change the color of the RGB status LED to signal that the program is searching for the server
bool serverFound = false; // stop when the server is found
IPAddress broadcastIp = ~WiFi.subnetMask() | WiFi.gatewayIP(); // Get the Broadcast IP of the local network (e.g. 192.168.0.255)
while (!serverFound)
{
// Send UDP Broadcast
udp.beginPacket(broadcastIp, localUdpPort);
udp.write(broadcastMessage);
udp.endPacket();
#if LOGGING
Serial.printf("[UDP] Sending UDP Broadcast on IP: %s, Port: %d, Message: %s\n", broadcastIp.toString().c_str(), localUdpPort, broadcastMessage);
#endif
delay(1000); // Pause a few milliseconds to avoid flooding the network
// Receive UDP packets
int packetSize = udp.parsePacket();
if (packetSize > 0)
{
// Read incoming UDP Packet
int len = udp.read(incomingPacket, 255);
if (len > 0)
{
incomingPacket[len] = 0;
}
#if LOGGING
Serial.printf("[UDP] Received %d bytes from %s, port %d\n", packetSize, udp.remoteIP().toString().c_str(), udp.remotePort());
Serial.printf("[UDP] Packet contents: %s\n", incomingPacket);
#endif
// Check if the received message is from the server we are searching for
if (strcmp(incomingPacket, broadcastMessage) == 0)
{
serverIp = udp.remoteIP();
serverPort = udp.remotePort();
#if LOGGING
Serial.printf("[UDP] Found Server on IP: %s, Port: %d\n", serverIp.toString().c_str(), serverPort);
#endif
serverFound = true;
changeColor(YELLOW, false); // Change status color of RGB LED back to yellow
}
}
}
}
Мне действительно интересно, что-то не так ссервер, сеть или NodeMcu.Тем более, что любой другой метод, который я пробовал, работал отлично, только не тогда, когда я отправляю его из NodeMcu.Любая помощь очень ценится!