Автоматизация связи через последовательный порт в Linux
У меня есть сервер linux (Red Hat 4) с одним подключением последовательного порта к встроенному Linux-устройству и другим подключением последовательного порта к контроллеру питания для этого устройства. Мой текущий способ контролировать их - открыть две сессии minicom, каждый в своем окне. Я хотел бы автоматизировать это общение через скрипты. Сначала я начал думать, как я могу автоматизировать использование minicom, а затем понял, что мне не нужно пытаться автоматизировать использование консольного приложения, когда script должен иметь возможность напрямую разговаривать с портом.
Я знаю некоторые Perl и некоторые python. У меня нет предыдущего опыта работы с модемной связью (с использованием AT-команд). У Perl есть Device:: Modem, хотя это только бета-версия, и Perl кажется хорошим выбором, потому что я предпочитаю его возможности для извлечения текста и пререкания. Но, если мне нужно научиться управлять модемом и писать/отлаживать script, что добавляет больше времени на мою задачу.
Возможно ли обычное интерактивное управление консольным приложением, например minicom, с помощью script? Если нет, то какие хорошие ресурсы для меня узнать, как использовать модемные AT-команды? Или есть еще один ресурс, который может упростить для меня вещи?
Ответы
Ответ 1
Kermit - это приложение для последовательной связи, такое как minicom, и имеет свой собственный язык script, и я использовал его для автоматической загрузки на встроенные устройства. Однако он довольно ограничен и/или глючит, поэтому я, наконец, переключился на использование python и pyserial.
Всякий раз, когда вы работаете с режимом texte, например, командой AT или разговариваете с оболочкой по последовательной линии, она действительно эффективна.
Если мне нужно выполнить двоичную передачу с использованием стандартного протокола, я обычно использую инструменты командной строки в неинтерактивном режиме и создаю их из своего python script.
Вот часть инструментов, которые я построил: ожидая ввода, отправки данных через 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')
Ответ 2
Я обнаружил runcript ( "$ man runningcript" ), утилиту, которая добавляет ожидаемую функцию скриптинга minicom. Мне кажется, что поведение ожидания полезно для меня, поскольку это устройство использует собственную интерактивную последовательность загрузки. Это рудиментарно, но достаточно. A script можно вызвать при запуске minicom с флагом "-S scriptname", а конкретный текст из script можно отправить в файл журнала, что полезно при запуске minicom из script. Я не нашел способ отправить содержимое консоли в журнал, поэтому, если внешний script знает, что происходит внутри minicom, необходимо записывать в журнал и script отслеживать журнал. Я планирую использовать скрипт только для перезагрузки и перехода к оболочке, затем ssh для устройства для реального взаимодействия, на языке более высокого уровня script, таком как Python или Perl. Если бы minicom еще не был на месте, я бы принял подход shodanex.
Runscript не может иметь вложенные ожидания. Я обошел это, используя goto и метки, которые, возможно, более читабельны, чем ожидали вложенные ожидания:
expect {
"Condition 1" goto lable1
}
lable1:
send "something"
expect {
"Condition 2" goto label2
}
lable2:
# etcetera
Ответ 3
Если это касается управления устройствами и ничего другого (например, обработка сообщений, взаимодействие с другими службами операционной системы и т.д.), вы можете использовать chat. Это написано именно для этого.
Вы можете найти его в пакете ppp на любом дистрибутиве Linux.
Ответ 4
Я использую такой контроллер питания, который я использую для управления RS232.
I script используя bash просто:
echo "your-command" > /dev/ttyUSB0
конкретное устройство, которое я использую, также использует 300 бод, поэтому я выдаю:
stty -F /dev/ttyUSB0 300
перед началом работы.
Ответ 5
Теперь у Python есть библиотека PySerial: http://pyserial.sourceforge.net/
У Ruby есть массив SerialPort: http://rubygems.org/gems/serialport
Perl, вероятно, имеет подобную библиотеку, но я не смог ее найти.
Я обнаружил их оба из очень полезной игровой площадки Arduino:
http://playground.arduino.cc//Main/Interfacing
CJ