Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use a pseudoterminal in python to emulate a serial port?

I am creating a python application using twisted which reads lines from a serial port. In order to (unit)test that app without having to connect an actual device to the serial port (also on pc's without an actual serial port) I would like to create a python script/app that sets up a virtual serial port and writes to it, so the twisted app can connect to the other end of the virtual serial port and read from it. This way I can write some unittests.

I found this is possible using pseudo terminals in linux. I also found a working example script on https://askubuntu.com/questions/9396/virtual-serial-port-for-testing-purpose.

I would like to change that script to a class on which I can call a write method to write data to the serial port, and then test the twisted app.

This example script does a lot of stuff with poll and select and a linux stty command which I don't really understand. I hope someone can fill the gap in my knowledge or provide some hints.

Cheers,

Dolf.

like image 204
Dolf Andringa Avatar asked Mar 02 '13 10:03

Dolf Andringa


People also ask

How do I create a serial port?

To configure the Serial Port for your device, on your computer go to Control Panel - Device Manager, select “High-Speed USB Serial Port (Com X)”, right click and select Properties. Click the Features tab. This tab is used to change the COM port number and configure the port.


1 Answers

In addition to what Jean-Paul Calderone said (which was the correct answer mostly), I also made the following script in python, using socat.

This can be imported and instantiated into an interpreter, and then you can use it's writeLine method to write data to a (vritual) serial port, which is connected through socat to another (virtual) serial port, on which another twisted app can be listening. But as Jean-Paul Calderone said: if it's just unittesting you want, you don't really need to do this stuff. Just read the docs he mentioned.

import os, subprocess, serial, time
from ConfigParser import SafeConfigParser


class SerialEmulator(object):
    def __init__(self,configfile):
        config=SafeConfigParser()
        config.readfp(open(configfile,'r'))
        self.inport=os.path.expanduser(config.get('virtualSerialPorts','inport'))
        self.outport=os.path.expanduser(config.get('virtualSerialPorts','outport'))
        cmd=['/usr/bin/socat','-d','-d','PTY,link=%s,raw,echo=1'%self.inport,'PTY,link=%s,raw,echo=1'%self.outport]
        self.proc=subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
        time.sleep(3)
        self.serial=serial.Serial(self.inport)
        self.err=''
        self.out=''
    def writeLine(self,line):
        line=line.strip('\r\n')
        self.serial.write('%s\r\n'%line)
    def __del__(self):
        self.stop()
    def stop(self):
        self.proc.kill()
        self.out,self.err=self.proc.communicate()
like image 87
Dolf Andringa Avatar answered Oct 29 '22 15:10

Dolf Andringa