Python中的虚拟串行设备?
我知道可以用比如说 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)
如果你创建更多的虚拟端口,即使它们的名字相同,不同的主控也会得到不同的文件描述符,这样就不会出现问题。