6
votes

I have a program, using pyserial, and I want to test it without using a real serial port device.

In windows, I use com0com, and in linux, I know there is a method to create virtual serial port pair without using additional program.

so I look up the manual, and found pts, /dev/ptmx, but I don't know how to create a pair by following the manual, can anyone give me a example?

I tried(in python):

f = open("/dev/ptmx", "r")

and it works, /dev/pts/4 is created.

and I tried:

f = open("/dev/4", "w")

and the result is:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 5] Input/output error: '/dev/pts/4'

edit: I found a solution(workround), using socat.

socat PTY,link=COM8 PTY,link=COM9

then COM8 COM9 are created as virtual serial port pair.

5

5 Answers

6
votes

I was trying to make an application that made use of virtual serial ports in order to communicate with some remote devices using TCP/Serial conversion... and I came across to a problem similar to yours. My solution worked out as follows:

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)

Although the name of the port of the master is the same if you check (/dev/ptmx) the fd is different if you create another master, slave pair, so reading from the master gets you the message issued to his assigned slave. I hope this helps you or anyone else that comes across a problem similar to this one.

4
votes

Per the docs, you need ptsname to get the name of the slave-side of the pseudo-terminal, and also, quoting the docs,

Before opening the pseudo-terminal slave, you must pass the master's file descriptor to grantpt(3) and unlockpt(3).

You should be able to use ctypes to call all of the needed functions.

1
votes

I don't know python but I can point you in the right direction: look here at a C code sample. Here's the man page for the /dev/ptmx. Make sure the permissions and owner is correct!. Here is the poster on the linuxquestions forum on how to use it from C.

0
votes

You should consider using the pty module instead, which should take care of this for you. (it opens /dev/ptmx or calls openpty or opens another appropriate device, depending on the platform.)

0
votes

You could build a dummy object that implements the same interface as the pySerial classes you use, but do something completely different and easily replicable like reading from and writing to files/terminal/etc.

For example:

class DummySerial():
  #you should consider subclassing this
  def __init__(self, *args, **kwargs):
    self.fIn = open("input.raw", 'r')
    self.fOut = open("output.raw", 'w')
    pass
  def read(self, bytes = 1):
    return self.fIn.read(bytes)
  def write(self, data):
    self.fOut.write(data)
  def close(self):
    self.fIn.close()
    self.fOut.close()
  #implement more methods here

If it quacks like a duck and it ducks like a duck...