两个 ESP32 上的 AsyncUDP 示例不工作:"WL_NO_SSID_AVAIL"

AsyncUDP example on two ESP32s not working: "WL_NO_SSID_AVAIL"

我正在尝试在两个 ESP32 DEVKITV1s 之间创建一个直接的客户端-服务器 WiFi 网络,由我的两台计算机的 USB 端口供电。

我已经使用 Arduino IDE(使用额外的开发板管理器 URL https://dl.espressif.com/dl/package_esp32_index.json)加载了示例并且 WiFi 状态(在两个开发板上)是 WL_NO_SSID_AVAIL.

客户代码:

#include "WiFi.h"
#include "AsyncUDP.h"

const char * ssid = "my_ssid";
const char * password = "my_password";

AsyncUDP udp;

void setup()
{
    Serial.begin(115200);
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    if (WiFi.waitForConnectResult() != WL_CONNECTED) {
        Serial.println("WiFi Failed");
        while(1) {
            delay(1000);
        }
    }
    if(udp.connect(IPAddress(192,168,1,100), 1234)) {
        Serial.println("UDP connected");
        udp.onPacket([](AsyncUDPPacket packet) {
            Serial.print("UDP Packet Type: ");
            Serial.print(packet.isBroadcast()?"Broadcast":packet.isMulticast()?"Multicast":"Unicast");
            Serial.print(", From: ");
            Serial.print(packet.remoteIP());
            Serial.print(":");
            Serial.print(packet.remotePort());
            Serial.print(", To: ");
            Serial.print(packet.localIP());
            Serial.print(":");
            Serial.print(packet.localPort());
            Serial.print(", Length: ");
            Serial.print(packet.length());
            Serial.print(", Data: ");
            Serial.write(packet.data(), packet.length());
            Serial.println();
            //reply to the client
            packet.printf("Got %u bytes of data", packet.length());
        });
        //Send unicast
        udp.print("Hello Server!");
    }
}

void loop()
{
    delay(1000);
    //Send broadcast on port 1234
    udp.broadcastTo("Anyone here?", 1234);
}

服务器代码:

#include "WiFi.h"
#include "AsyncUDP.h"

const char * ssid = "my_ssid";
const char * password = "my_password";

AsyncUDP udp;

void setup()
{
    Serial.begin(115200);
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    if (WiFi.waitForConnectResult() != WL_CONNECTED) {
        Serial.println("WiFi Failed");
        while(1) {
            delay(1000);
        }
    }
    if(udp.listen(1234)) {
        Serial.print("UDP Listening on IP: ");
        Serial.println(WiFi.localIP());
        udp.onPacket([](AsyncUDPPacket packet) {
            Serial.print("UDP Packet Type: ");
            Serial.print(packet.isBroadcast()?"Broadcast":packet.isMulticast()?"Multicast":"Unicast");
            Serial.print(", From: ");
            Serial.print(packet.remoteIP());
            Serial.print(":");
            Serial.print(packet.remotePort());
            Serial.print(", To: ");
            Serial.print(packet.localIP());
            Serial.print(":");
            Serial.print(packet.localPort());
            Serial.print(", Length: ");
            Serial.print(packet.length());
            Serial.print(", Data: ");
            Serial.write(packet.data(), packet.length());
            Serial.println();
            //reply to the client
            packet.printf("Got %u bytes of data", packet.length());
        });
    }
}

void loop()
{
    delay(1000);
    //Send broadcast
    udp.broadcast("Anyone here?");
}

其他人有没有遇到问题运行他们的 ESP32 上使用 Arduino IDE 的示例代码?

综上所述,我的误区是:

  1. AsyncUDP 示例不允许直接的客户端-服务器通信。它需要一个中间路由器,例如家用路由器。这是因为 WiFi.mode(WIFI_STA) 设置 - 服务器需要设置为 WiFi.mode(WIFI_AP) 才能连接到其他 ESP32。
  2. 客户端和服务端都需要使用udp.listen(端口)函数来接收消息(这里可以指定端口)。要发送消息,请对服务器使用 udp.broadcast(message),对客户端使用 udp.broadcastTo(message, port)。

以下代码是我可以使它仍然有效的最小示例。我确信有更好的示例可用,但这是我在没有 HTTP 请求的情况下使用中间路由器等在两个 ESP32 之间进行通信的示例的方式...

客户端:

#include "WiFi.h"
#include "AsyncUDP.h"

const char * ssid = "my_ssid";
const char * password = "my_password";

AsyncUDP udp;

int port = 1234;

void setup() {
    Serial.begin(115200);
    WiFi.mode(WIFI_STA); // Make this the client (the server is WIFI_AP)
    WiFi.begin(ssid, password);
    delay(100);

    Serial.print("Connecting...");
    // Display a period every 0.5 s to show the user something is happening.
    while (WiFi.waitForConnectResult() != WL_CONNECTED) { 
      Serial.print(".");    
      delay(500);
    }
    Serial.println("");

    if(udp.listen(port)) {
        udp.onPacket([](AsyncUDPPacket packet) {
          Serial.print("Received data: ");
            Serial.write(packet.data(), packet.length());
            Serial.println();
        });
    }
}

void loop(){
    delay(1000);
    udp.broadcastTo("A message for the server from the client.", port);
}

服务器端:

#include "WiFi.h"
#include "AsyncUDP.h"

const char *my_ssid = "my_ssid";
const char *password = "my_password";

int port = 1234;

AsyncUDP udp;

void setup(){
    Serial.begin(115200);
    WiFi.mode(WIFI_AP);
    WiFi.softAP(my_ssid, password);
    delay(100);

      if(udp.listen(port)) {
        udp.onPacket([](AsyncUDPPacket packet) {
            Serial.print("Data: ");
            Serial.write(packet.data(), packet.length());
            Serial.println();  
          });
      }
}

void loop() {
    delay(1000);
    udp.broadcastTo("Anyone here? Love from the server.", port);
}

这只是对 Jeremy 回答的适度补充。 文本指出服务器使用 udp.broadcast(message) 而客户端使用 udp.broadcastTo(message, port) 另一方面,所提供的代码两边都使用 broadcastTo 。 我想知道为什么会这样,在查看源代码 AsyncUPD.cpp 之后,我看到 udp.broadcast 实际上会通过调用 udp.broadcastTo 并将本地端口用作第二个参数来完成它的工作。 参考:https://github.com/espressif/arduino-esp32/blob/master/libraries/AsyncUDP/src/AsyncUDP.cpp 第 809 行。 这是一个小细节,但我认为值得一提。它允许我配对相同类型的 ESP32 板,并且(对我来说最重要的是)使用相同的代码进行 UDP 迭代。因此,这两个板可以一起工作(分层或不分层)或自主工作。