如何在 Node.js 中的同一进程内监听同一地址上的不同 UDP 端口
How to listen to different UDP ports on the same address within the same process in Node.js
我正在编写一个 Node.js 应用程序来控制一架小型无人机。以下是来自 SDK 的说明:
使用 Wi-Fi 在 Tello 和 PC、Mac 或移动设备之间建立连接。
发送命令并接收响应
特洛 IP:192.168.10.1 UDP 端口:8889 <<-->> PC/Mac/Mobile
第 1 步:在 PC、Mac 或移动设备上设置 UDP 客户端,以通过同一端口从 Tello 发送和接收消息。
第 2 步:在发送任何其他命令之前,通过 UDP 端口 8889 发送 'command' 到 Tello 以启动 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的消息。必须先完成第1和2步,然后才能尝试执行此步骤3.
接收 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 发送 'streamon' 到 Tello 以开始流式传输。必须先完成第 1 步和第 2 步,然后才能尝试第 5 步。
命令和接收部分非常有效,我正在发送和接收数据报 to/from 端口 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();
这里是使用"streamon"命令接收和解码Tello SDK团队提供的h264视频流的示例代码。 https://github.com/dji-sdk/Tello-Python.
接收到的视频流数据的具体处理方法请参考doc/reademe.pdf和h264解码器路径下的源码
在 运行 示例代码之前,您应该使用安装脚本安装一些依赖项。
您是否打开防火墙以接受 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.
我正在编写一个 Node.js 应用程序来控制一架小型无人机。以下是来自 SDK 的说明:
使用 Wi-Fi 在 Tello 和 PC、Mac 或移动设备之间建立连接。
发送命令并接收响应
特洛 IP:192.168.10.1 UDP 端口:8889 <<-->> PC/Mac/Mobile
第 1 步:在 PC、Mac 或移动设备上设置 UDP 客户端,以通过同一端口从 Tello 发送和接收消息。
第 2 步:在发送任何其他命令之前,通过 UDP 端口 8889 发送 'command' 到 Tello 以启动 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的消息。必须先完成第1和2步,然后才能尝试执行此步骤3.
接收 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 发送 'streamon' 到 Tello 以开始流式传输。必须先完成第 1 步和第 2 步,然后才能尝试第 5 步。
命令和接收部分非常有效,我正在发送和接收数据报 to/from 端口 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();
这里是使用"streamon"命令接收和解码Tello SDK团队提供的h264视频流的示例代码。 https://github.com/dji-sdk/Tello-Python. 接收到的视频流数据的具体处理方法请参考doc/reademe.pdf和h264解码器路径下的源码
在 运行 示例代码之前,您应该使用安装脚本安装一些依赖项。
您是否打开防火墙以接受 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.