在 Linux 上自动化串行端口通信

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3874597/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 23:35:59  来源:igfitidea点击:

Automating serial port communication on Linux

linuxautomated-testsserial-portmodem

提问by jasper77

I have a linux server (Red Hat 4) with one serial port connection to an embedded linux device, and another serial port connection to a power controller for that device. My current way to control them is to open two minicom sessions, each in its own window. I would like to automate this communication through scripts. At first, I began to think how I could automate using minicom, then realized I shouldn't need to try to automate using a console application when a script should be able to speak to the port directly.

我有一个 linux 服务器(Red Hat 4),一个串行端口连接到嵌入式 linux 设备,另一个串行端口连接到该设备的电源控制器。我目前控制它们的方法是打开两个 minicom 会话,每个会话都在自己的窗口中。我想通过脚本自动化这种通信。起初,我开始思考如何使用 minicom 实现自动化,然后意识到当脚本应该能够直接与端口对话时,我不应该尝试使用控制台应用程序实现自动化。

I know some Perl and some python. I do not have previous experience with modem communication (using AT commands). Perl has Device::Modem, though it's only beta, and Perl seems like a good choice because I prefer its text extraction and wrangling abilities. But, if I need to learn how to control a modem and write/debug a script, that adds more time to my task.

我知道一些 Perl 和一些 python。我以前没有调制解调器通信的经验(使用 AT 命令)。Perl 有 Device::Modem,虽然它只是测试版,但 Perl 似乎是一个不错的选择,因为我更喜欢它的文本提取和整理能力。但是,如果我需要学习如何控制调制解调器和编写/调试脚本,这会为我的任务增加更多时间。

Is it possible/common to interactively control a console app like minicom with a script? If not, what are some good resources for me to learn how to use modem AT commands? Or is there another resource out there that could simplify things for me?

是否可以/常见使用脚本以交互方式控制像 minicom 这样的控制台应用程序?如果没有,有什么好的资源可以让我学习如何使用调制解调器 AT 命令?或者有没有其他资源可以为我简化事情?

采纳答案by shodanex

Kermit is a serial communication app like minicom and it has its own script language, and I used it for some automatic upload on embedded devices. However, it is quite limited and/or buggy, so I finally switched to using python and pyserial.
Whenever you deal with texte mode, like AT command set or speaking to a shell over a serial line, it is really powerful.

Kermit 是一个类似于 minicom 的串行通信应用程序,它有自己的脚本语言,我用它在嵌入式设备上进行了一些自动上传。但是,它非常有限和/或有问题,所以我最终切换到使用 python 和 pyserial。
每当您处理 texte 模式时,例如 AT 命令集或通过串行线路与 shell 对话,它都非常强大。

If I need to do binary transfer using some standard protocol, I usually use command line tools in non interactive mode, and spawn them from my python script.

如果我需要使用一些标准协议进行二进制传输,我通常在非交互模式下使用命令行工具,并从我的 python 脚本中生成它们。

Here is some part of the tools I built : waiting for some input, sending data through xmodem, sending a command to u-boot and starting a transfer using the kermit protocol. I use it for automatic flashing and testing of embedded devices.

这是我构建的部分工具:等待输入、通过 xmodem 发送数据、向 u-boot 发送命令并使用 kermit 协议开始传输。我用它来自动刷新和测试嵌入式设备。

class Parser :
    def __init__(self, sport_name):
        self.currentMsg = ''
        if sport_name :
            self.ser = serial.Serial(sport_name, 115200)
    def WaitFor(self, s, timeOut=None):
        self.ser.timeout = timeOut
        self.currentMsg = ''
        while self.currentMsg.endswith(s) != True :
            # should add a try catch here
            c=self.ser.read()
            if c != '' :
                self.currentMsg += c
                sys.stdout.write(c)
            else :
                print 'timeout waiting for ' + s
                return False
        return True

    def XmodemSend(self,fname):
        if not self.WaitFor('C', 1) :
            print 'RomBOOT did not launch xmodem transfer'
            return
        self.ser.flushInput()
        self.ser.close()
        call(["xmodem","-d",self.ser.port,"-T",fname])
        self.ser.open() 

def UbootLoad(self, fname):
    self.ser.write('loadb 0x20000000\n')
    if not self.WaitFor('bps...',1) :
        print 'loadb command failed'
        sys.exit()
    self.ser.flushInput()
    self.ser.close()
    retcode=call(['kermit','-y','kermit_init','-s',fname])
    if retcode != 0 :
        print 'error sending' + fname
        sys.exit()
    self.ser.open()
    self.UbootCmd('echo\n')

回答by user237419

If it's just about controlling the devices and nothing else (like processing messages, interacting with other operating system services, etc) you can use the chatprogram. It's written exactly for this. You may find it in the ppppackage on any Linux distro.

如果只是控制设备而不是其他任何事情(例如处理消息、与其他操作系统服务交互等),您可以使用聊天程序。正是为此而写的。您可以在任何 Linux 发行版的ppp包中找到它。

回答by Mcradle

I'm using such a power controller which I use RS232 to control.

我正在使用这样的电源控制器,我使用 RS232 进行控制。

I script it using bash simply by issuing:

我只是通过发出以下命令来使用 bash 编写脚本:

echo "your-command" > /dev/ttyUSB0

the specific device I'm using also uses 300 baud rate so I issue:

我使用的特定设备也使用 300 波特率,所以我发出:

stty -F /dev/ttyUSB0 300

before hand.

在手之前。

回答by jasper77

I discovered runscript ("$ man runscript"), a utility that adds an expect-like scripting ability to minicom. The expect behavior is useful to me since this device uses a proprietary interactive boot sequence. It's rudimentary but sufficient. A script can be invoked when starting minicom with the "-S scriptname" flag, and specific text from within the script can be sent to a log file, which is useful when running minicom from a script. I haven't found a way to send console content to a log, so having an external script know what's going on inside minicom involves writing to a log and having the script monitor the log. I plan to use runscript only to restart and get to a shell, then ssh to the device for real interaction, within a higher level language script such as Python or Perl. If minicom weren't already in place, I would take shodanex's approach.

我发现了 runscript ("$ man runscript"),这是一个向 minicom 添加类似期望脚本功能的实用程序。期望行为对我很有用,因为该设备使用专有的交互式启动序列。这是基本的但足够了。使用“-S scriptname”标志启动 minicom 时可以调用脚本,并且可以将脚本中的特定文本发送到日志文件,这在从脚本运行 minicom 时很有用。我还没有找到将控制台内容发送到日志的方法,因此让外部脚本知道 minicom 内部发生了什么涉及写入日志并让脚本监视日志。我计划仅使用 runscript 来重新启动并访问 shell,然后在更高级别的语言脚本(如 Python 或 Perl)中通过 ssh 连接到设备以进行真正的交互。如果 minicom 不是

Runscript cannot have nested expects. I got around this by using goto's and labels, which is arguably more readable than nested expects anyway:

Runscript 不能有嵌套的期望。我通过使用 goto 和标签解决了这个问题,无论如何,它比嵌套期望的更具可读性:

expect {
   "Condition 1"  goto lable1
}

lable1:
    send "something"
    expect {
       "Condition 2"  goto label2
    }
lable2:
    # etcetera

回答by CJ.

Python now has the PySerial library: http://pyserial.sourceforge.net/

Python 现在有 PySerial 库:http://pyserial.sourceforge.net/

Ruby has the SerialPort gem: http://rubygems.org/gems/serialport

Ruby 有 SerialPort gem:http: //rubygems.org/gems/serialport

Perl probably has a similar library, but I was unable to find it.

Perl 可能有一个类似的库,但我找不到它。

I discovered both of these from the very useful Arduino Playground: http://playground.arduino.cc//Main/Interfacing

我从非常有用的 Arduino Playground 中发现了这两个:http: //playground.arduino.cc//Main/Interface

CJ

CJ