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

问题描述 投票:0回答:6

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

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

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

linux automated-tests serial-port modem
6个回答
6
投票

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

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

这是我构建的工具的一部分:等待一些输入,通过 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')

6
投票

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

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

expect {
   "Condition 1"  goto lable1
}

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

3
投票

我正在使用这样一个电源控制器,我使用RS232来控制。

我使用 bash 编写脚本,只需发出:

echo "your-command" > /dev/ttyUSB0

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

stty -F /dev/ttyUSB0 300

手前。


2
投票

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


1
投票

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

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

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

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

CJ


0
投票

使用 picocom

回答
#!/bin/bash

# barf on error
set -e
# configure port, exit immediately, don't reset
picocom -qrX -b 115200 ... other settings ... /dev/ttyS0
# send contents of cmd.txt, line by line, 
# waiting 1 sec in-between, after host sends reply
while read ln; do
     echo "$ln" | picocom -qrix 1000 /dev/ttyS0
done < cmd.txt

取自链接

© www.soinside.com 2019 - 2024. All rights reserved.