Python读写tty

时间:2021-05-20 21:01:47

BACKGROUND: If you want, skip to the problem section

背景:如果需要,请跳至问题部分

I am working on a front end for test equipment. The purpose of the front end is to make it easier to write long test scripts. Pretty much just make them more human readable and writable.

我正在研究测试设备的前端。前端的目的是使编写长测试脚本更容易。几乎只是让它们更具人类可读性和可写性。

The equipment will be tested using a Prologix GPIB-USB Controller (see prologix.biz). We found a tutorial at http://heliosoph.mit-links.info/gpib-on-debian-linux-the-easy-way/ and did all of the steps, and it worked!

该设备将使用Prologix GPIB-USB控制器进行测试(参见prologix.biz)。我们在http://heliosoph.mit-links.info/gpib-on-debian-linux-the-easy-way/找到了一个教程,并完成了所有步骤,并且它有效!

As we don't have the test equipment yet, we wanted to write an emulator in Python using openpty. We do have the GPIB-USB Controller, just not what gets connected to that. I got the emulator working as a perfect replacement for the GPIB-USB. This means that I would follow the "GPIB on Debian ..." tutorial (above) and get output that I programmed the emulator to return. The input and output were done in the same manner as the tutorial just reading and writing to/from a pty device (ie /dev/pts/2) instead of the tty (ie /dev/ttyUSB0).

由于我们还没有测试设备,我们想用openpty在Python中编写一个模拟器。我们确实有GPIB-USB控制器,而不是那些与之相关的控制器。我让仿真器成为GPIB-USB的完美替代品。这意味着我将遵循“Debian上的GPIB ...”教程(上面)并获得我编程模拟器返回的输出。输入和输出的方式与教程只是读取和写入pty设备(即/ dev / pts / 2)而不是tty(即/ dev / ttyUSB0)相同。

Now that the emulator works, we want to write a front end that can be used to write scripts easily. The goal is to make a kind of macro system that writes a bunch of commands when we call a function.

现在仿真器工作了,我们想要编写一个可以轻松编写脚本的前端。我们的目标是创建一种在调用函数时写入一堆命令的宏系统。

PROBLEM: exists using both the emulator and the device

问题:使用模拟器和设备存在

I am using the following Python functions to read, write, and open the tty/pty devices, but I am not getting the same result that I get if I just use echo and cat in bash.

我正在使用以下Python函数来读取,写入和打开tty / pty设备,但是如果我在bash中使用echo和cat,我得到的结果不一样。

tty = os.open(tty_path, os.O_RDWR)
os.read(tty, 100)
os.write(tty, "++ver")

for example, I would expect the following to be equivalent

例如,我希望以下内容是等效的

$ cat < /dev/pty/2 &   # According to the tutorial, this must be run in parallel
$ echo "++ver" > /dev/pty/2
Prologix GPIB Version 1.2.3.4 ...

and

tty = os.open("/dev/pyt/2", os.o_RDWR)
os.read(tty, 100) # In separate Thread to be run in parallel
os.write(tty, "++ver") # in main thread

The output is very different, please explain why and how I can fix it.

输出是非常不同的,请解释为什么以及如何解决它。

FULL CODE is here: http://pastebin.com/PWVsMjD7

完整的代码在这里:http://pastebin.com/PWVsMjD7

2 个解决方案

#1


6  

Well, I asked too soon. I hope someone benefits from this self answer.

好吧,我太早问了。我希望有人从这个自我答案中受益。

So this works to read and write from both the emulator and the actual device. I am not exactly sure why, and would appreciate an explanation, but this does work in all of my tests

因此,这适用于从仿真器和实际设备读取和写入。我不确定为什么,并希望得到解释,但这在我的所有测试中都有效

import serial

class VISA:
    def __init__(self, tty_name):
        self.ser = serial.Serial()
        self.ser.port = tty_name
        # If it breaks try the below
        #self.serConf() # Uncomment lines here till it works

        self.ser.open()
        self.ser.flushInput()
        self.ser.flushOutput()

        self.addr = None
        self.setAddress(0)

    def cmd(self, cmd_str):
        self.ser.write(cmd_str + "\n")
        sleep(0.5)
        return self.ser.readline()

    def serConf(self):
        self.ser.baudrate = 9600
        self.ser.bytesize = serial.EIGHTBITS
        self.ser.parity = serial.PARITY_NONE
        self.ser.stopbits = serial.STOPBITS_ONE
        self.ser.timeout = 0 # Non-Block reading
        self.ser.xonxoff = False # Disable Software Flow Control
        self.ser.rtscts = False # Disable (RTS/CTS) flow Control
        self.ser.dsrdtr = False # Disable (DSR/DTR) flow Control
        self.ser.writeTimeout = 2

    def close(self):
        self.ser.close()

#2


2  

You do not actually have to use any special module to read from TTY.
Option O_NOCTTY solved my problems with CDCACM example MCU app.
I'm sure it will work for you (as you work on Linux too).

您实际上不必使用任何特殊模块来读取TTY。选项O_NOCTTY解决了CDCACM示例MCU应用程序的问题。我相信它会对你有用(因为你也在Linux上工作)。

#!/usr/bin/env python3

import io, os

tty = io.TextIOWrapper(
        io.FileIO(
            os.open(
                "/dev/ttyACM1",
                os.O_NOCTTY | os.O_RDWR),
            "r+"))

for line in iter(tty.readline, None):
    print(line.strip())

#1


6  

Well, I asked too soon. I hope someone benefits from this self answer.

好吧,我太早问了。我希望有人从这个自我答案中受益。

So this works to read and write from both the emulator and the actual device. I am not exactly sure why, and would appreciate an explanation, but this does work in all of my tests

因此,这适用于从仿真器和实际设备读取和写入。我不确定为什么,并希望得到解释,但这在我的所有测试中都有效

import serial

class VISA:
    def __init__(self, tty_name):
        self.ser = serial.Serial()
        self.ser.port = tty_name
        # If it breaks try the below
        #self.serConf() # Uncomment lines here till it works

        self.ser.open()
        self.ser.flushInput()
        self.ser.flushOutput()

        self.addr = None
        self.setAddress(0)

    def cmd(self, cmd_str):
        self.ser.write(cmd_str + "\n")
        sleep(0.5)
        return self.ser.readline()

    def serConf(self):
        self.ser.baudrate = 9600
        self.ser.bytesize = serial.EIGHTBITS
        self.ser.parity = serial.PARITY_NONE
        self.ser.stopbits = serial.STOPBITS_ONE
        self.ser.timeout = 0 # Non-Block reading
        self.ser.xonxoff = False # Disable Software Flow Control
        self.ser.rtscts = False # Disable (RTS/CTS) flow Control
        self.ser.dsrdtr = False # Disable (DSR/DTR) flow Control
        self.ser.writeTimeout = 2

    def close(self):
        self.ser.close()

#2


2  

You do not actually have to use any special module to read from TTY.
Option O_NOCTTY solved my problems with CDCACM example MCU app.
I'm sure it will work for you (as you work on Linux too).

您实际上不必使用任何特殊模块来读取TTY。选项O_NOCTTY解决了CDCACM示例MCU应用程序的问题。我相信它会对你有用(因为你也在Linux上工作)。

#!/usr/bin/env python3

import io, os

tty = io.TextIOWrapper(
        io.FileIO(
            os.open(
                "/dev/ttyACM1",
                os.O_NOCTTY | os.O_RDWR),
            "r+"))

for line in iter(tty.readline, None):
    print(line.strip())