Nodejs 如何在 'data' 事件上访问 SerialPort 路径
Nodejs how to access SerialPort path on 'data' event
我正在使用 nodejs 中的 SerialPort 库来列出可用端口,并向每个端口发送数据。如果其中任何一个 return “OK”,我想找出 return 是哪个端口:
SerialPort.list().then(ports => {
ports.forEach(port => {
var rtuSocket = new SerialPort(port.path, { baudRate: 9600 }, (err, data) => {
rtuSocket.on('data', (err, data) => {
console.log(rtuSocket.path)
console.log("[RTU][CONNECTED]")
})
rtuSocket.write("AT")
})
})
})
很明显,rtuSocket 在时间数据 return 之前将是一个不同的变量。有没有办法知道哪个端口正在 returning .on("data") 中的数据?
您需要某种超时来检测端口是否没有响应。我还强烈建议您检查响应数据并发送比简单的“AT”命令更多的东西,因为许多其他设备响应 AT 命令,例如游戏 PC 的 RGB 控制器和一些配置为调制解调器的 Android 手机。
像下面这样的东西应该可以工作:
function checkPort (path, callback) { // callback(error, path)
let sock = new SerialPort(path, { baudRate: 9600 }, (err, data) => {
let timer = setTimeout(() => {
callback(new Error('Timeout'));
}, 100); // 100ms should be enough. If not increase it
sock.on('data', (err, data) => {
clearTimeout(timer); // clear the timer
if (err) {
return callback(err);
}
else {
return callback(null, path);
}
})
sock.write("AT");
})
}
现在您可以检查哪个端口已连接:
function findConnectedPort (callback) {
SerialPort.list().then(ports => {
portCount = ports.length;
ports.forEach(port => {
checkPort(port.path, (err, foundPath) => {
if (err) {
// Ignore errors or deal with them how you want
}
else {
// Great! Got response. Return the path:
if (portCount > 0) { // prevent calling callback
// more than once
callback(null, foundPath);
}
portCount = 0;
}
portCount--;
if (portCount <= 0) {
// Well, none of the ports responded so we
// return an error:
callback(new Error('Not found'));
}
})
})
})
}
现在要找到连接的端口,只需执行以下操作:
findConnectedPort((err,path) => {
if (err) {
console.error(err);
}
else {
console.log("RTU CONNECTED at " + path);
// Do what you need with the port here...
}
})
承诺和async/await
虽然上面的代码有效。对于像这样需要大量条件逻辑的异步代码,我发现使用 async/await 更容易推理。为此,您需要将代码转换为 return promises:
function checkPort (path) {
return new Promise((resolve, reject) => {
let sock = new SerialPort(path, { baudRate: 9600 }, (err, data) => {
let timer = setTimeout(() => {
reject(new Error('Timeout'));
}, 100); // 100ms should be enough. If not increase it
sock.on('data', (err, data) => {
clearTimeout(timer); // clear the timer
if (err) {
return reject(err);
}
else {
return resolve(path);
}
})
sock.write("AT");
})
});
}
现在 for 循环更容易理解,尽管现在您不能使用 forEach
或 map
或 filter
或任何数组方法。如果要使用 async/await:
,则需要使用 for
或 while
async function findConnectedPort () {
let ports = await SerialPort.list();
for (let i=0; i<ports.length; i++) {
let port = ports[i];
try {
// return the first successful result:
return await checkPort(port.path);
}
catch (err) {
// ignore errors or handle them how you like
// just remember that we use an error to signal
// a timeout which simply means no device
// responded
}
}
// we didn't find anything. In this case I prefer to return
// nothing instead of returning an error:
return null;
}
现在您可以通过以下操作简单地获取连接的端口:
async function main () {
let connectedPath = await findConnectedPort();
if (connectedPath === null) {
console.log('No devices found!');
}
else {
// Do what you need with the port here...
}
}
main();
我正在使用 nodejs 中的 SerialPort 库来列出可用端口,并向每个端口发送数据。如果其中任何一个 return “OK”,我想找出 return 是哪个端口:
SerialPort.list().then(ports => {
ports.forEach(port => {
var rtuSocket = new SerialPort(port.path, { baudRate: 9600 }, (err, data) => {
rtuSocket.on('data', (err, data) => {
console.log(rtuSocket.path)
console.log("[RTU][CONNECTED]")
})
rtuSocket.write("AT")
})
})
})
很明显,rtuSocket 在时间数据 return 之前将是一个不同的变量。有没有办法知道哪个端口正在 returning .on("data") 中的数据?
您需要某种超时来检测端口是否没有响应。我还强烈建议您检查响应数据并发送比简单的“AT”命令更多的东西,因为许多其他设备响应 AT 命令,例如游戏 PC 的 RGB 控制器和一些配置为调制解调器的 Android 手机。
像下面这样的东西应该可以工作:
function checkPort (path, callback) { // callback(error, path)
let sock = new SerialPort(path, { baudRate: 9600 }, (err, data) => {
let timer = setTimeout(() => {
callback(new Error('Timeout'));
}, 100); // 100ms should be enough. If not increase it
sock.on('data', (err, data) => {
clearTimeout(timer); // clear the timer
if (err) {
return callback(err);
}
else {
return callback(null, path);
}
})
sock.write("AT");
})
}
现在您可以检查哪个端口已连接:
function findConnectedPort (callback) {
SerialPort.list().then(ports => {
portCount = ports.length;
ports.forEach(port => {
checkPort(port.path, (err, foundPath) => {
if (err) {
// Ignore errors or deal with them how you want
}
else {
// Great! Got response. Return the path:
if (portCount > 0) { // prevent calling callback
// more than once
callback(null, foundPath);
}
portCount = 0;
}
portCount--;
if (portCount <= 0) {
// Well, none of the ports responded so we
// return an error:
callback(new Error('Not found'));
}
})
})
})
}
现在要找到连接的端口,只需执行以下操作:
findConnectedPort((err,path) => {
if (err) {
console.error(err);
}
else {
console.log("RTU CONNECTED at " + path);
// Do what you need with the port here...
}
})
承诺和async/await
虽然上面的代码有效。对于像这样需要大量条件逻辑的异步代码,我发现使用 async/await 更容易推理。为此,您需要将代码转换为 return promises:
function checkPort (path) {
return new Promise((resolve, reject) => {
let sock = new SerialPort(path, { baudRate: 9600 }, (err, data) => {
let timer = setTimeout(() => {
reject(new Error('Timeout'));
}, 100); // 100ms should be enough. If not increase it
sock.on('data', (err, data) => {
clearTimeout(timer); // clear the timer
if (err) {
return reject(err);
}
else {
return resolve(path);
}
})
sock.write("AT");
})
});
}
现在 for 循环更容易理解,尽管现在您不能使用 forEach
或 map
或 filter
或任何数组方法。如果要使用 async/await:
for
或 while
async function findConnectedPort () {
let ports = await SerialPort.list();
for (let i=0; i<ports.length; i++) {
let port = ports[i];
try {
// return the first successful result:
return await checkPort(port.path);
}
catch (err) {
// ignore errors or handle them how you like
// just remember that we use an error to signal
// a timeout which simply means no device
// responded
}
}
// we didn't find anything. In this case I prefer to return
// nothing instead of returning an error:
return null;
}
现在您可以通过以下操作简单地获取连接的端口:
async function main () {
let connectedPath = await findConnectedPort();
if (connectedPath === null) {
console.log('No devices found!');
}
else {
// Do what you need with the port here...
}
}
main();