вторник, 31 марта 2015 г.

Работа с COM портом из командной строки. Мониторинг

...вот все-таки батники незаслуженно игнорируются любителями высокоуровневых языков, а тем не менее даже на них можно решить задачи по мониторингу не только удаленных хостов, но и мониторинга COM-порта, что под DOS, что под Windows. К примеру, возникла задача реагирования (запуска какого-либо приложения) на приход сигнала на один из пинов, кнопка к примеру (выставить DTR тот же и замкнуть с CTS).


Напомню еще раз распиновку COM-порта:
 Номер вывода Наименование Характер сигнала Сигнал
 1 DCD Входной Data carrier detect
 2 RxD Выходной Transmit data
 3 TxD Входной Receive data
 4 DTR Выходной Data terminal ready
 5 GND - Ground
 6 DSR Входной Data set ready
 7 RTS Выходной Request to send
 8 CTS Входной Clear to send
 9 RI Входной Ring indicator
Нам нужно управлять состоянием устройства ввода-вывода. Одной из таких команд - mode (синтаксис см. по mode /?):



Что мы видим? Видим возможность установки скорости, паритета, служебных пинов, паритета и иже с ними. А что нам даст обращение (mode com1) к конкретному COM-порту? А вот сие даст:



Cостояние пинов и настроек порта. Можем прочитать? Можем. Для этого воспользуемся FIND="параметр" (важно точное указание всех знаков):
@ echo off
mode com1 dtr=on > nul
:m1
mode com1 | find "CTS:     ON" > nul
if errorlevel=1 goto m1
if errorlevel=0 start notepad.exe

Флаги:
  •  "dtr=on" установит единичку на DTR.
  •  "> nul" - этим мы убираем вывод ответа на экран.
  •  "errorlevel" - отрабатываем результат выполнения.

Если команда FIND не нашла в ответе "CTS: ON", то повторить опрос по циклу. Ежели нашла, запустит блокнот.

Настроить COM порт:
mode com46:19200,n,8,1,p
Передача в COM-порт

Отослать число в COM порт через ECHO (служит для вывода текста в стандартный поток вывода информации):
echo ^1> \\.\com46
Если же вам нужен полный контроль отсылаемых символов (байтов) без лишних нечитаемых и извращением с экранированием символов, то самое верное и простое - создать текстовый файл, записать туда нужный пакет данных в бинарном виде и воспользоваться старым и надежным copy myfile.ext > \\.\com46. Простенько и со вкусом )))

Прием из COM-порта

Сразу в файл:
type COMn>output.ext

Ссылки по тематике
  1. Виртуальный или... железный
  2. Удаленный COM-порт по TCP/IP

4 комментария:

  1. Добрый день.
    Подскажите как сделать из командной строки в Windows XP это:

    Аппаратный перезапуск модемов iRZ MC35S и iRZ MC35PU
    Новые модемы iRZ MC35S и iRZ MC35PU имеют возможность принудительного перезапуска с помощью внешней программы. Функция реализуется путём восьмикратного поднятия-опускания сигнала DTR в течение заданного времени. Рекомендуемые значения: 0.5 сек импульс, 0.5 сек пауза.
    Утилита для Windows:DTR8X.exe (474.50 KB)
    Для Linux можно использовать следующий Perl-скрипт:
    ---------------------------DTR8X.pl----------------------------------------
    #!/usr/bin/perl -w
    # yum install perl-Device-SerialPort # Fedora
    # apt-get install libdevice-serialport-perl # Debian
    # ./DTR8X.pl /dev/ttyUSB0 # syntax
    use Device::SerialPort;
    my $device = '/dev/ttyS0'; # default device
    my $milliseconds = 500; # 0.5s delay
    my $count = 8;
    $device = $ARGV[0] if ($#ARGV == 0); # get device from command line
    my $port=new Device::SerialPort($device) || die "new($device): $! ";
    for (my $i = 0; $i <= $count; $i++) { $port->pulse_dtr_off($milliseconds); }

    ОтветитьУдалить
    Ответы
    1. Доброго времени суток. Когда речь о виндах, можно реализовать VBS скриптом (прямо в блокноте) через OLE DynamicWrapperX или X.2, обращаясь прямо к WinAPI функциям (в частности, открыть порт по CreateFile() и дергая EscapeCommFunction() c заданной задержкой).

      По сути так:

      "SETDTR = 5 ' Set DTR high
      CLRDTR = 6 ' Set DTR low
      ' открываем нужный нам порт COM1
      hFile = Wrap.CreateFile("COM1", GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
      ' опускаем DTR
      s = Wrap.EscapeCommFunction(hFile, 6)

      cnt=1
      ' запускаем цикл до 8
      Do While cnt<9
      WScript.Sleep 500 'кол-во мc
      s = Wrap.EscapeCommFunction(hFile, SETDTR)
      WScript.Sleep 500 'кол-во мc
      s = Wrap.EscapeCommFunction(hFile, CLRDTR)
      cnt=cnt+1
      Loop
      Wrap.CloseHandle(hFile)"



      Полный сабж залил сюда.

      Удалить
  2. Касательно командной строки в Windows XP: штатной задержки sleep в языке сценариев не реализовано, а timeout появился только с висты. Да и то в секундах. Потому как вариант реализации чистого пакетного файла через подсчет сотых долей секунды:

    @ echo off

    echo %time%
    echo Wait 500 ms (n*0.01sec)...
    for /l %%i in (1,1,8) do (
    mode com1 dtr=on > nul
    call :sleep 50
    mode com1 dtr=off > nul
    call :sleep 50
    )
    echo %time%
    pause
    exit /b

    :sleep
    :: пауза в сотых долях сек
    setlocal
    call :gettick
    set /a finish=%errorlevel%+%1
    if %finish% geq 8640000 set finish=0
    :slplabel
    call :gettick
    if %errorlevel% lss %finish% goto slplabel
    endlocal & exit /b

    :gettick
    :: долей сек, прошедших с начала дня
    setlocal
    set t=%time: =0%
    set /a tick=1%t:~9,2%-100+(1%t:~6,2%-100)*100+(1%t:~3,2%-100)*6000+(1%t:~0,2%-100)*360000
    endlocal & exit /b %tick%

    Данный код создаст 8 импульсов по DTR в цикле. Удачи!

    ОтветитьУдалить
  3. Всегда пожалуйста.

    ОтветитьУдалить

В комментариях уважайте собеседника, внимательно читайте посты и не додумывайте. Просьбы и предложения из разряда: «можно ваш Skype/Viber/телефон», «напишите мне в vk/FB», а также другие им подобные — игнорируются. Выход новых версий ПО, внешняя ссылка, переставшая работать с течением времени и т.п. не является основанием для претензий. Желающие спокойно подискутировать и высказаться — Welcome. Желающие спонсировать блог — Donate. Нарушение этих простых правил ведет к бану и удалению комментариев без предупреждения.