如何在开发过程中模拟串口?

时间:2015-02-27 18:44:51

标签: node.js serial-port raspberry-pi

我正在为我的Raspberry Pi开发一个node.js应用程序,它从串口接收数据,但是我没有直接在它上面开发应用程序,而是使用我的主计算机。所以我在app.js

中有这段代码
var serialport = require("serialport");
var SerialPort = serialport.SerialPort;
var sp = new SerialPort("/dev/ttyACM0", {
    parser: serialport.parsers.readline("\n")
});

sp.on("data", function (rawData) {
...

这在Rasperry Pi上运行良好,但我希望能够首先在我的开发计算机上运行该应用程序,而不必评论有关串行端口的每个代码块。

实现这一目标的最佳方法是什么?有没有办法模拟串口?

2 个答案:

答案 0 :(得分:2)

AFAIK,目前还没有任何图书馆本地执行此操作。我过去所做的是使用node-serialport库自己的测试代码作为示例,例如:https://github.com/voodootikigod/node-serialport/blob/master/test_mocks/linux-hardware.js

如果您查看该文件,他们会为自己的测试嘲笑串口行为,您可以简单地复制他们在那里做的事情并在您的内容中使用它,您应该是很高兴。

希望有所帮助!

答案 1 :(得分:0)

我需要同样的东西,但无法找到具体操作方法的详细信息,但是在我的搜索中一直遇到这个问题。经过一些研究并在不同领域找到了一些模糊的参考资料,我能够将以下内容放在一起。希望这对可能登陆这里的其他人有所帮助。

您可以使用自己的类扩展 SerialPort - MockBindings 类,然后简单地实现一个自定义 write 函数,该函数将接收数据,形成正确的响应,然后将其发送回调用者。

const MockSerialBinding = require('@serialport/binding-mock');

class EmulatedDeviceSerialBinding extends MockSerialBinding {
    constructor(opt = {}) {
        super(opt);
    }

    // THIS IS THE METHOD THAT GETS TRIGGERED WHEN THE CODE TO TEST WRITES TO A DEVICE
    async write(buffer) {
        // Use this method to detect the supported commands and emulate a response
        const cmd = Buffer.from(buffer).toString();

        let response = 'Unknown Command!'; // Default response

        // Custom logic here to determine the proper response

        super.emitData(response);
    }
}

module.exports = EmulatedDeviceSerialBinding;

为了您的测试,准备一个可以使用上述类的假串行设备:

const SerialPort = require('serialport');
SerialPort.Binding = EmulatedDeviceSerialBinding;

// Setup a new mock serial device that can be the target
EmulatedDeviceSerialBinding.createPort('ttyUSB_TestTarget', {
    echo: true,
    readyData: '\r\nhostname@user:~$ ' // This will append a 'prompt' to the end of each response (like a linux terminal would)
});

现在您的逻辑将是相同的,只是您将连接到模拟设备端口而不是真实端口。以下是 Express Route 中间件的片段:

const SerialPort = require('serialport');
const SerialRegexParser = require('@serialport/parser-regex');

const serialParser = new SerialRegexParser({regex: /(?<Prompt>.*[$#]\s*$)/m});

const serialPortOptions = {
    baudRate: 115200
};

// The req.params.devicePort value be the name of the emulated port
const port = new SerialPort(req.params.devicePort, serialPortOptions, (err) => {
    if (err) {
        return res.status(400).send({error: err.message});
    }
});
port.pipe(serialParser);

// THIS WILL BE TRIGGERED WHEN THE EmulatedDeviceSerialBinding does the emitData call
serialParser.once('data', (data) => {
    if (res.headersSent) return; // We've already responded to the client, we can't send more

    const dataString = Buffer.from(data).toString();

    // Remove the command executed from the beginning if it was echoed
    respDoc.data = dataString.replace(cmdToExecute, '').trimEnd();

    return res.send(respDoc);
});

// Send the command to the device 
// THIS WILL TRIGGER THE EmulatedDeviceSerialBinding.write() FUNCTION
port.write(cmdToExecute, (err) => {
    if (err) {
        return res.status(400).send({error: err.message});
    }
});

程序流程为:

Express 中间件 port.write(cmdToExecute) -> EmulatedDeviceSerialBinding.write() -> Express Middleware serialParser.once('data') 回调