【问题标题】:How to listen to different UDP ports on the same address within the same process in Node.js如何在 Node.js 中的同一进程内侦听同一地址上的不同 UDP 端口
【发布时间】:2019-05-28 11:55:08
【问题描述】:

我正在编写一个 Node.js 应用程序来控制一架小型无人机。以下是 SDK 的说明:


使用 Wi-Fi 在 Tello 和 PC、Mac 或移动设备之间建立连接。

发送命令并接收响应

Tello IP:192.168.10.1 UDP 端口:8889 > PC/Mac/Mobile

第 1 步:在 PC、Mac 或移动设备上设置 UDP 客户端,通过同一端口从 Tello 发送和接收消息。

第 2 步:在发送任何其他命令之前,通过 UDP PORT 8889 向 Tello 发送“command”以启动 SDK 模式。

接收 Tello 状态

Tello IP:192.168.10.1 -->> PC/Mac/Mobile UDP 服务器:0.0.0.0 UDP 端口:8890

第 3 步:在 PC、Mac 或移动设备上设置 UDP 服务器,并通过 UDP PORT 8890 检查来自 IP 0.0.0.0 的消息。在尝试第 3 步之前,必须完成第 1 步和第 2 步。

接收 Tello 视频流

Tello IP:192.168.10.1 -->> PC/Mac/Mobile UDP 服务器:0.0.0.0 UDP 端口:11111

第 4 步:在 PC、Mac 或移动设备上设置 UDP 服务器,并通过 UDP PORT 11111 检查来自 IP 0.0.0.0 的消息。

第 5 步:通过 UDP 端口 8889 向 Tello 发送“streamon”以开始流式传输。必须先完成第 1 步和第 2 步,然后再尝试第 5 步。


命令和接收部分就像一个魅力,我正在端口 8889 上向/从无人机发送和接收数据报。我的问题是我似乎没有在其他端口上收到任何状态或视频流消息而且我很确定这不是无人机的问题,而是我没有正确设置 Node.js 的问题。任何人都可以看到我的实施中的问题所在。这是我的代码:

tello.ts

import dgram from 'dgram';

export class Tello {
  private LOCAL_IP_ = '0.0.0.0';
  private TELLO_IP_ = '192.168.10.1';

  private COMMAND_PORT_ = 8889;
  private commandSocket_ = dgram.createSocket('udp4');

  private STATE_PORT_ = 8890;
  private stateSocket_ = dgram.createSocket('udp4');

  private VIDEO_PORT_ = 11111;
  private videoSocket_ = dgram.createSocket('udp4');

  constructor() {}

  startCommandSocket() {
    this.commandSocket_.addListener('message', (msg, rinfo) => {
      const message = msg.toString();
      console.log(`from ${rinfo.address}: ${message}`);
    });
    this.commandSocket_.bind(this.COMMAND_PORT_, this.LOCAL_IP_, () => {
      console.log('Started listening on the command socket');
    });
  }

  startStateSocket() {
    this.stateSocket_.addListener('message', (msg, rinfo) => {
      const message = msg.toString();
      console.log(`from ${rinfo.address}: ${message}`);
    });
    this.stateSocket_.bind(this.STATE_PORT_, this.LOCAL_IP_, () => {
      console.log('Started listening on the state socket');
    });
  }

  startVideoSocket() {
    this.videoSocket_.addListener('message', (msg, rinfo) => {
      console.log('receiving video');      
      const message = msg.toString();
      console.log(`from ${rinfo.address}: ${message}`);
    });
    this.videoSocket_.bind(this.VIDEO_PORT_, this.LOCAL_IP_, () => {
      console.log('Started listening on the video socket');
    });
  }

  private sendCommand_(command: string) {
    // As this is sent over UDP and we have no guarantee that the packet is received or a response given
    // we are sending the command 5 times in a row to add robustess and resiliency.
    //for (let i = 0; i < 5; i++) {
    this.commandSocket_.send(command, this.COMMAND_PORT_, this.TELLO_IP_);
    //}
    console.log(`sending command: ${command} to ${this.TELLO_IP_}`);
  }

  /**
   * Enter SDK mode.
   */
  command() {
    this.sendCommand_('command');
  }

  /**
   * Auto takeoff.
   */
  takeoff() {
    this.sendCommand_('takeoff');
  }

  /**
   * Auto landing.
   */
  land() {
    this.sendCommand_('land');
  }

  streamVideoOn() {
    this.sendCommand_('streamon');
  }

  streamVideoOff() {
    this.sendCommand_('streamoff');
  }

  ...

}

index.ts

import { waitForSeconds } from './utils';
import { Tello } from './tello'

const main = async () => {
  const tello = new Tello();

  tello.startCommandSocket();
  await waitForSeconds(1);
  tello.command();
  await waitForSeconds(1);  
  tello.startStateSocket();
  await waitForSeconds(1);
  tello.startVideoSocket();
  await waitForSeconds(1);
  tello.streamVideoOn();
  await waitForSeconds(1);
    
  tello.takeoff();
  await waitForSeconds(10);
  tello.land(); 
};

main();

【问题讨论】:

  • 虽然这不能解决你的问题,但我注意到了一件小事:你不需要将你的 COMMAND_PORT 绑定到本地端口 8889。你需要 send() 命令到端口 8889,但是你的客户端套接字真的可以在任何端口打开。
  • 您的本地服务器似乎是正确的。我建议您尝试打开一个 UDP 客户端并向您的本地端口 8890 和 11111 发送一些消息,以确保它们正常工作。您可能会发现问题出在其他地方。
  • @LucioPaiva 根据您的建议,我已经在我的计算机上启动了一个单独的节点进程,并做了一个简单的 socket.send('Foo', 8890) 和 socket.send('Bar', 11111) 和两者都被我的应用程序拾取。我对 UDP 网络的理解非常有限。那是一个相关的测试吗?这说明什么?这是否意味着我的代码很好,并且还有其他东西阻止 Tello 与我的应用程序通信?如果是这样,您知道问题可能是什么吗?
  • 酷,这表明您的 UDP 服务器正在工作。接下来,我将尝试从另一台机器上运行该单独的 Node 进程,以查看如果远程访问服务器是否仍然可以访问。如果是这样,那么我可能会再看一下无人机文档,看看我是否遗漏了什么。

标签: javascript node.js typescript udp dji-sdk


【解决方案1】:

这里是接收和解码由 Tello SDK 团队提供的 h264 视频流的示例代码,使用“streamon”命令。 ​https://github.com/dji-sdk/Tello-Python.​​​ 接收到的视频流数据的具体处理方法请参考doc/reademe.pdf和h264解码器路径下的源码。

在运行示例代码之前,您应该使用安装脚本安装一些依赖项。

【讨论】:

    【解决方案2】:

    您是否打开防火墙以接受 UDP 端口 8890 / 11111 ?

    在您的笔记本电脑防火墙中打开端口 8890/udp 和 11111/udp 以接收 Tello 遥测数据。

    在 Linux 上

    $ sudo firewall-cmd --permanent --add-port=8890/udp

    $ sudo firewall-cmd --permanent --add-port=11111/udp

    在 Mac 上,使用系统偏好设置打开端口。

    Open System Preferences > Security & Privacy > Firewall > Firewall Options
    Click the + / Add button
    Choose 'node' application from the Applications folder and click Add.
    Ensure that the option next to the application is set to Allow incoming connections.
    Click OK.
    

    【讨论】:

    • 我在 Windows 10 上,但你发现了问题,我能够打开端口,现在一切正常。
    猜你喜欢
    • 1970-01-01
    • 2011-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-13
    • 2017-05-31
    • 2012-11-01
    相关资源
    最近更新 更多