【问题标题】:Virtual Serial Device in Python?Python中的虚拟串行设备?
【发布时间】:2011-01-18 12:07:25
【问题描述】:

我知道我可以使用例如pySerial 与串行设备通信,但如果我现在没有设备但仍需要为其编写客户端怎么办?如何在 Python 中编写“虚拟串行设备”并与 pySerial 对话,就像我会运行本地 Web 服务器一样?也许我只是没有很好地搜索,但我一直无法找到有关此主题的任何信息。

【问题讨论】:

    标签: python serial-port pyserial virtual-serial-port


    【解决方案1】:

    到目前为止,这是我为我所做并为我解决的事情:

    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)
    

    如果您创建更多虚拟端口,则不会有任何问题,因为不同的 master 会获得不同的文件描述符,即使它们具有相同的名称。

    【讨论】:

    • 这在 Windows 上不起作用,缺少 pty 所需的 termios 模块。
    • 我似乎能够很好地从假设备读取数据(即我有另一个程序在端点s_name 处写入设备),但每当我发出ser.write("...") 时,该文本就会得到下次我os.read(master,1000) 时回显,无论是否有任何东西连接到端口,并且端口的另一端似乎没有获取数据。
    • 当我在 Ubuntu 14.04 中运行您的代码时,出现以下错误:File "<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
    • @SamuelGóngora 另见:stackoverflow.com/questions/34831131/…,我认为这可能是问题的更准确原因。
    • pyserial 的单元测试有一组很好的例子:github.com/pyserial/pyserial/blob/…
    【解决方案2】:

    我能够使用以下代码模拟任意串行端口./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 does not play well with virtual port

    【讨论】:

    • 你在 GitHub 上的某个地方有这个代码吗?为什么我需要有 'ttydevice' 和 'ttyclient'?我想要一个 python 程序(设备模拟器),我将作为一个单独的进程运行。它将创建“./ttymydevice”并回复我的串行命令,因为它是一个真正的设备。
    【解决方案3】:

    使用com0com(如果您在 Windows 上)之类的东西来设置虚拟串行端口并在此基础上进行开发可能会更容易。

    【讨论】:

    • 是否有免费的com0com 替代方案(带有API)可以在我的商业软件as it is 中使用?我只需要用户拥有虚拟串口
    【解决方案4】:

    如果您运行的是 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 上接收,反之亦然。

    【讨论】:

      【解决方案5】:

      如果您需要在不访问设备的情况下测试应用程序,那么循环设备可能会完成这项工作。它包含在 pySerial 2.5 https://pythonhosted.org/pyserial/url_handlers.html#loop

      【讨论】:

        【解决方案6】:

        这在一定程度上取决于您现在要完成的工作...

        您可以将对串行端口的访问封装在一个类中并编写一个实现以使用套接字 I/O 或文件 I/O。然后编写您的串行 I/O 类以使用相同的接口,并在设备可用时将其插入。 (这实际上是一种无需外部硬件即可测试功能的好设计。)

        或者,如果您要将串行端口用于命令行界面,您可以使用 stdin/stdout。

        或者,还有关于 virtual serial devices for linux 的其他答案。

        【讨论】:

        • 是的,写一个复制pySerial接口的“虚拟串口设备”类。然后您的代码可以互换使用您的“虚拟设备”类或真正的 pySerial 接口。
        • 这是一个很好的实现,因为它很容易实现并且适用于所有平台!
        • 很抱歉更新这个旧帖子,但您能详细说明一下吗?这对我很有帮助。谢谢
        猜你喜欢
        • 1970-01-01
        • 2015-03-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-28
        • 2016-01-17
        • 2014-01-03
        相关资源
        最近更新 更多