How to listen to different UDP ports on the same address within the same process in Node.js

谁说我不能喝 提交于 2021-02-19 05:26:07

问题


I'm writing a Node.js app to control a small drone. Here are the instructions from the SDK:


Use Wi-Fi to establish a connection between the Tello and PC, Mac, or mobile device.

Send Command & Receive Response

Tello IP: 192.168.10.1 UDP PORT: 8889 <<-->> PC/Mac/Mobile

Step 1: Set up a UDP client on the PC, Mac, or mobile device to send and receive message from the Tello via the same port.

Step 2: Before sending any other commands, send 'command' to the Tello via UDP PORT 8889 to initiate SDK mode.

Receive Tello State

Tello IP: 192.168.10.1 -->> PC/Mac/Mobile UDP Server: 0.0.0.0 UDP PORT: 8890

Step 3: Set up a UDP server on the PC, Mac, or mobile device and check the message from IP 0.0.0.0 via UDP PORT 8890. Steps 1 and 2 must be completed before attempting step 3.

Receive Tello Video Stream

Tello IP: 192.168.10.1 -->> PC/Mac/Mobile UDP Server: 0.0.0.0 UDP PORT: 11111

Step 4: Set up a UDP server on the PC, Mac, or mobile device and check the message from IP 0.0.0.0 via UDP PORT 11111.

Step 5: Send 'streamon' to the Tello via UDP PORT 8889 to start streaming. Steps 1 and 2 must be completed before attempting step 5.


The Command & Receive part works like a charm and I am sending and receiving datagrams to/from the drone on port 8889. My problem is that it looks like I'm not receiving any State or Video Stream messages on the other ports and I'm pretty sure that it's not a problem with the drone but something I'm not setting up properly with Node. Can anyone see where the problem is in my implementation. Here is my code:

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();

回答1:


Did you open your firewall to accept UDP ports 8890 / 11111 ?

Open port 8890/udp and 11111/udp in your laptop firewall to receive Tello telemetry data.

On Linux

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

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

On Mac, use System Preferences to open the ports.

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.



回答2:


Here is the sample code that receives and decodes the h264 video stream provided by Tello SDK team, using the "streamon" command. ​https://github.com/dji-sdk/Tello-Python.​​ Please refer to doc/reademe.pdf and the source code under the path of h264 decoder for the specific processing method of the received video stream data.

Before you run the sample code, you should install some dependencies by using the install script.



来源:https://stackoverflow.com/questions/53996098/how-to-listen-to-different-udp-ports-on-the-same-address-within-the-same-process

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!