Virtual Serial Device in Python?

北慕城南 提交于 2019-11-28 16:12:32

this is something I did and worked out for me so far:

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)

If you create more virtual ports you will have no problems as the different masters get different file descriptors even if they have the same name.

It may be easier to using something like com0com (if you're on Windows) to set up a virtual serial port, and develop on that.

Dave Bacher

It depends a bit on what you're trying to accomplish now...

You could wrap access to the serial port in a class and write an implementation to use socket I/O or file I/O. Then write your serial I/O class to use the same interface and plug it in when the device is available. (This is actually a good design for testing functionality without requiring external hardware.)

Or, if you are going to use the serial port for a command line interface, you could use stdin/stdout.

Or, there's this other answer about virtual serial devices for linux.

Patrick Steadman

I was able to emulate an arbitrary serial port ./foo using this code:

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 needs to be installed (sudo apt-get install socat), as well as the pyserial python package (pip install pyserial).

Open the python interpreter and import SerialEmulator:

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

Your client program can then wrap ./ttyclient with pyserial, creating the virtual serial port. You could also make client_port /dev/ttyUSB0 or similar if you can't modify client code, but might need sudo.

Also be aware of this issue: Pyserial does not play well with virtual port

If you are running Linux you can use the socat command for this, like so:

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

When the command runs, it will inform you of which serial ports it has created. On my machine this looks like:

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]

Now I can write to /dev/pts/13 and receive on /dev/pts/12, and vice versa.

steko

Maybe a loop device will do the job if you need to test your application without access to a device. It's included in pySerial 2.5 https://pythonhosted.org/pyserial/url_handlers.html#loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!