我知道可以使用例如pySerial来与串行设备通信,但是如果我现在没有设备却需要编写一个客户端,我该怎么办呢?如何在Python中编写一个“虚拟串行设备”,并让pySerial与其通信,就像运行本地Web服务器一样?也许我只是搜索得不好,但我一直找不到关于这个主题的任何信息。
我知道可以使用例如pySerial来与串行设备通信,但是如果我现在没有设备却需要编写一个客户端,我该怎么办呢?如何在Python中编写一个“虚拟串行设备”,并让pySerial与其通信,就像运行本地Web服务器一样?也许我只是搜索得不好,但我一直找不到关于这个主题的任何信息。
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)
如果您创建更多的虚拟端口,则即使它们具有相同的名称,不同的主机也会获得不同的文件描述符,从而避免了问题。
./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()
./ttyclient
封装起来,创建虚拟串口。如果无法修改客户端代码,则可以将client_port设置为/dev/ttyUSB0
或类似的内容,但可能需要sudo
权限。此外还要注意这个问题:Pyserial与虚拟端口不兼容。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
接收,反之亦然。如果你在Windows系统上,可以使用类似com0com的工具来设置虚拟串口,然后进行开发。这样可能会更加方便。
com0com
替代品(带API),我可以在我的商业软件中原样
使用?我只需要用户拥有虚拟串口。 - mrid如果您需要在没有设备访问权限的情况下测试应用程序,那么循环设备可能可以胜任。它包含在pySerial 2.5中 https://pythonhosted.org/pyserial/url_handlers.html#loop
s_name
写入设备),但是每当我发出ser.write("...")
时,该文本只会在下一次os.read(master,1000)
时被回显,无论是否连接到端口,而且端口的另一端似乎没有收到数据。 - PonkadoodleFile "<stdin>", line 1, in <module> File "/usr/local/lib/python2.7/dist-packages/serial/serialutil.py", line 180, in __init__ self.open() File "/usr/local/lib/python2.7/dist-packages/serial/serialposix.py", line 311, in open self._update_dtr_state() File "/usr/local/lib/python2.7/dist-packages/serial/serialposix.py", line 605, in _update_dtr_state fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str) IOError: [Errno 22] Invalid argument
- Samuel Góngora