我目前正在使用node-serialport
模块进行串口通信。我将发送一个命令ATEC
,它将以ECHO
回复。
但是,这个发送和接收数据的过程是异步的(在我发送数据之后,我不知道数据何时到达data
事件),示例代码如下:
//Register the data event from the serial port
port.on('data', (data) => {
console.log(data);
});
//Send data using serialport
port.write('ATEC');
无论如何我能以这种方式写出来吗?
//When i send the command, I could receive the data
port.write('ATEC').then((data)=> {
console.log(data);
});
这可能实现吗?
在使用request
客户端的http通信中,我们可以执行类似
request.get('http:\\google.com')
.on('response', (res) => {
console.log(res);
});
我想使用serialport
答案 0 :(得分:1)
我正在研究的项目中存在类似的问题。需要一个串行的同步发送/接收循环,而serialport包使这有点奇怪。
我们的解决方案是创建串行端口“数据”事件服务的某种函数/ promises / generators /等队列(取决于您的体系结构)。每次写东西时,都要将一个函数/ promise / etc放入队列中。
让我们假设您只是将函数抛入队列中。当触发“data”事件时,它会将当前聚合的接收缓冲区作为参数发送到队列的第一个元素中,该元素可以查看它是否包含所需的所有数据,如果是,则对其进行处理,并且以某种方式将自己从队列中移除。
这允许您使用相同的基本机制处理多种不同类型的体系结构(回调/承诺/协程/等)。
作为一个额外的好处:如果您完全控制协议的两面,您可以在这些字符串的末尾添加“\ n”,然后使用serialport的“readline”解析器,这样您就只能获得数据整个字符串上的事件。如果有问题,可能会比不断检查输入有效性更容易。
<强>更新强>
现在该代码已经完成并经过测试(参见http://github.com/metafetish/buttshock-js中的ET312模块),以下是我的工作方式:
function writeAndExpect(data, length) {
return new Promise((resolve, reject) => {
const buffer = new Buffer(length);
this._port.write(data, (error) => {
if (error) {
reject(error);
return;
}
});
let offset = 0;
let handler = (d) => {
try {
Uint8Array.from(d).forEach(byte => buffer.writeUInt8(byte, offset));
offset += d.length;
} catch (err) {
reject(err);
return;
}
if (offset === length) {
resolve(buffer);
this._port.removeListener("data", handler);
};
};
this._port.on("data", handler);
});
}
上面的函数获取uint8s列表,并返回预期的数据量,返回一个promise。我们编写数据,然后将自己设置为“数据”事件处理程序。我们使用它来读取,直到我们得到我们期望的数据量,然后解决承诺,将自己移除为“数据”监听器(这很重要,否则你将堆叠处理程序!),以及光洁度。
此代码非常符合我的需求,并且不会处理除已知参数的非常严格的发送/接收对之外的情况,但它可能会让您有一个想法开始。
答案 1 :(得分:1)
我在串行数据接收中包装了一个承诺
function sendSync(port, src) {
return new Promise((resolve, reject) => {
port.write(src);
port.once('data', (data) => {
resolve(data.toString());
});
port.once('error', (err) => {
reject(err);
});
});
}
请注意,该活动使用once
代替on
来阻止事件堆叠(请查看以下评论以获取更多信息 - 感谢@DKebler发现它)
然后,我可以将代码编写为同步,如下所示
sendSync(port, 'AThello\n').then((data) => {
//receive data
});
sendSync(port, 'ATecho\n').then((data) => {
//receive data
});
或者我可以使用co
包
co(function* () {
const echo = yield sendSync(port, 'echo\n');
const hello = yield sendSync(port, 'hello 123\n');
return [echo, hello]
}).then((result) => {
console.log(result)
}).catch((err) => {
console.error(err);
})