如何解决Node.js如何在'data'事件中访问SerialPort路径 承诺和异步/等待
我正在使用nodejs中的SerialPort库列出可用端口,并将数据发送到每个端口。如果其中任何一个返回“ OK”,我想找出返回它的端口:
SerialPort.list().then(ports => {
ports.forEach(port => {
var rtuSocket = new SerialPort(port.path,{ baudrate: 9600 },(err,data) => {
rtuSocket.on('data',data) => {
console.log(rtuSocket.path)
console.log("[RTU][CONNECTED]")
})
rtuSocket.write("AT")
})
})
})
很明显,在返回数据时,rtuSocket将是一个不同的变量。有没有办法知道哪个端口正在返回.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',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,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更加容易推理。为此,您需要转换代码以返回承诺:
function checkPort (path) {
return new Promise((resolve,reject) => {
let sock = new SerialPort(path,data) => {
let timer = setTimeout(() => {
reject(new Error('Timeout'));
},100); // 100ms should be enough. If not increase it
sock.on('data',data) => {
clearTimeout(timer); // clear the timer
if (err) {
return reject(err);
}
else {
return resolve(path);
}
})
sock.write("AT");
})
});
}
现在,尽管现在无法使用forEach
或map
或filter
或任何数组方法,但for循环更易于理解。如果要使用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();
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。