Nodejs映射串口写入以接收数据

时间:2016-06-10 04:34:59

标签: javascript node.js promise

我目前正在使用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

复制相同的行为

2 个答案:

答案 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);
    })