Python中的虚拟串行设备?

57 投票
6 回答
63822 浏览
提问于 2025-04-15 19:27

我知道可以用比如说 pySerial 来和串口设备交流,但如果我现在没有设备,还是需要为它写一个客户端,该怎么办呢?我怎么能在 Python 中写一个“虚拟串口设备”,让 pySerial 和它对话,就像我运行一个本地的网页服务器一样?也许我搜索得不够好,但我找不到关于这个话题的任何信息。

6 个回答

10

我用下面的代码成功模拟了一个任意的串口 ./foo

这是一个叫做 SerialEmulator.py 的文件。

import os, subprocess, serial, time

# this script lets you emulate a serial device
# the client program should use the serial port file specifed by client_port

# if the port is a location that the user can't access (ex: /dev/ttyUSB0 often),
# sudo is required

class SerialEmulator(object):
    def __init__(self, device_port='./ttydevice', client_port='./ttyclient'):
        self.device_port = device_port
        self.client_port = client_port
        cmd=['/usr/bin/socat','-d','-d','PTY,link=%s,raw,echo=0' %
                self.device_port, 'PTY,link=%s,raw,echo=0' % self.client_port]
        self.proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        time.sleep(1)
        self.serial = serial.Serial(self.device_port, 9600, rtscts=True, dsrdtr=True)
        self.err = ''
        self.out = ''

    def write(self, out):
        self.serial.write(out)

    def read(self):
        line = ''
        while self.serial.inWaiting() > 0:
            line += self.serial.read(1)
        print line

    def __del__(self):
        self.stop()

    def stop(self):
        self.proc.kill()
        self.out, self.err = self.proc.communicate()

你需要先安装 socat(可以用命令 sudo apt-get install socat),还需要安装 pyserial 这个 Python 包(用 pip install pyserial 命令)。

接下来,打开 Python 解释器并导入 SerialEmulator:

>>> from SerialEmulator import SerialEmulator
>>> emulator = SerialEmulator('./ttydevice','./ttyclient') 
>>> emulator.write('foo')
>>> emulator.read()

然后,你的客户端程序可以用 pyserial 来包装 ./ttyclient,这样就创建了一个虚拟串口。如果你不能修改客户端代码,也可以把 client_port 设置为 /dev/ttyUSB0 或类似的路径,但可能需要加上 sudo 权限。

另外要注意一个问题:Pyserial 和虚拟端口的兼容性不好

10

如果你在使用Linux系统,可以用一个叫做 socat 的命令来实现这个功能,方法如下:

socat -d -d pty,raw,echo=0 pty,raw,echo=0

当这个命令运行时,它会告诉你它创建了哪些串口。在我的电脑上,显示的内容是:

2014/04/23 15:47:49 socat[31711] N PTY is /dev/pts/12
2014/04/23 15:47:49 socat[31711] N PTY is /dev/pts/13
2014/04/23 15:47:49 socat[31711] N starting data transfer loop with FDs [3,3] and [5,5]

现在我可以往 /dev/pts/13 发送数据,同时也可以从 /dev/pts/12 接收数据,反过来也可以。

56

这是我做过的一些事情,到目前为止对我有效:

import os, pty, serial

master, slave = pty.openpty()
s_name = os.ttyname(slave)

ser = serial.Serial(s_name)

# To Write to the device
ser.write('Your text')

# To read from the device
os.read(master,1000)

如果你创建更多的虚拟端口,即使它们的名字相同,不同的主控也会得到不同的文件描述符,这样就不会出现问题。

撰写回答