[an error occurred while processing this directive] IT • archiv :: Print

IT • archiv


[an error occurred while processing this directive]

[an error occurred while processing this directive]

Доступ к COM порту из Java приложения

[an error occurred while processing this directive](none) [an error occurred while processing this directive](none)[an error occurred while processing this directive] ::
[an error occurred while processing this directive](none)
[an error occurred while processing this directive]([an error occurred while processing this directive] Владислав Каменский [an error occurred while processing this directive])

[an error occurred while processing this directive](none)
PDF versionPDF версия
Обзор
Эта статья посвящена обзору пакета javax.comm, позволяющего получить доступ с COM порту компьютера. Данный пакет не входит в стандартный набор JDK.

Итак, сформулируем задачу. Для примера возьмем обычный модем, который проинсталлирован на стандартный COM порт, нам необходимо, что бы он откликался на терминальные команды (AT, ATDP и т.д.), посылаемые ему из java приложения.

Для того, чтобы мы могли написать такое приложение, нам необходимо скачать пакет классов javax.com (см.[2]). После чего, необходимо совершить ряд манипуляций, чтобы написанные нами приложения могли корректно работать.

Инсталляция Java Communications API для JDK 1.2 (Windows)

<jdk> корневой каталог JDK. Если вы проинсталлировали JDK в каталог c:\jdk1.2тогда замените все ссылки <jdk> на c:\jdk1.2.

  1. Положите файл win32com.dll в директорию <jdk>\jre\bin .
  2. Положите архив comm.jar в директорию <jdk>\jre\lib\ext.
  3. Положите файл javax.comm.properties в <jdk>\jre\lib .
  4. Не изменяйте переменную CLASSPATH.
Замечание
В настоящее время существуют реализации пакета для следующих платформ Windows, Solaris, Linux. (см. [2]).

Только после проделанной работы команды javac и java, смогут правильно работать.

Замечание
Если вы используете версию JDK ниже, чем 1.2 то вам придется по другому проинсталлировать данный пакет (см. [2])

Рассмотрим следующий фрагмент кода:

import javax.comm.*;
import java.util.*;

. . .

public static void main(String[] args) {
 Enumeration portList = CommPortIdentifier.getPortIdentifiers();
   while (portList.hasMoreElements()) {
   CommPortIdentifier portId =
         (CommPortIdentifier) portList.nextElement();
       if (portId.getPortType() ==
           CommPortIdentifier.PORT_SERIAL) {
            if (portId.getName().equals("COM2")) {
                    Terminal terminal = new Termianl(portID);
            }
       }
  }
}

Класс CommPortIdentifier

Приведем описание переменных и методов класса CommPortIdentifier:

Переменные класса:

  • PORT_SERIAL public static final int PORT_SERIAL
    RS-232 последовательный порт
  • PORT_PARALLEL public static final int PORT_PARALLEL
    IEEE 1284 параллельный порт

Методы Класса:

  • public static Enumeration getPortIdentifiers()
    Метод возвращает объект типа enumeration, который содержит объекты типа CommPortIdentifier для каждого порта системы.
  • public String getName()
    Возвращает имя порта . Например, "COM1" и "COM2" на PC;
  • public int getPortType()
    Метод возвращает тип порта PORT_SERIAL или PORT_PARALLEL.
  • public synchronized CommPort open(String appname, int timeout) throws PortInUseException
    Открывает порт. Возвращает объект типа CommPort. параметры:
    • appname - Имя приложения вызывающего данный метод. (произвольная строка)
    • timeout - время в милисекундах, в течение которого, блокируется доступ к порту для его открытия.
    Throws: PortInUseException если порт используется другим приложением.

Пример использования: класс Terminal

Таким образом, в методе main, мы получили полный перечень идентификаторов портов нашего компьютера, после чего отобрали идентификаторы последовательных портов. Ну, и наконец, выбрали идентификатор COM2 порта (предположим что модем находится именно на нем) и передали его конструктору класса Terminal. Следующим шагом будет написание класса Terminal, который бы смог отправлять сообщения в COM порт, и прослушивал бы сообщения поступающие из этого порта.

import javax.comm.*;
import java.io.*;

 public class Terminal implements Runnable,
                    SerialPortEventListener {
    InputStream inputStream;
    OutputStream outputStream;
    SerialPort serialPort;
    Thread readThread;
    String[] messageString = {"AT\n","ATI1\n","ATI3\n"};
public Terminal() {
   try {
 serialPort = (SerialPort) portId.open("TerminalApp", 2000);
} catch (PortInUseException e) {}
    try {
outputStream = serialPort.getOutputStream();
inputStream = serialPort.getInputStream();
    } catch (IOException e) {}
    try {
        serialPort.addEventListener(this);
    } catch (TooManyListenersException e) {}
    serialPort.notifyOnDataAvailable(true);
    try {
       // устанавливаем параметры порта
       serialPort.setSerialPortParams(9600,
                SerialPort.DATABITS_8,
                SerialPort.STOPBITS_1,
                SerialPort.PARITY_NONE);
    } catch (UnsupportedCommOperationException e) {}
    readThread = new Thread(this);
    readThread.start();
}
public void run() {
 for(int i=0;i<3;i++){
   try {
        outputStream.write(messageString[i].getBytes());
  }catch (IOException e) {}
  try{
    Thread.sleep(5000);
  } catch (InteruptedException e) {}
 }
  System.exit(1); // выход из программы
}
public void serialEvent(SerialPortEvent event) {
   switch(event.getEventType()) {
        case SerialPortEvent.BI:
        case SerialPortEvent.OE:
        case SerialPortEvent.FE:
        case SerialPortEvent.PE:
        case SerialPortEvent.CD:
        case SerialPortEvent.CTS:
        case SerialPortEvent.DSR:
        case SerialPortEvent.RI:
        case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
break;
        case SerialPortEvent.DATA_AVAILABLE:
            byte[] readBuffer = new byte[20];
            try {
                while (inputStream.available() > 0) {
                    int numBytes = inputStream.read(readBuffer);
                }
                System.out.print(new String(readBuffer));
            } catch (IOException e) {}
            break;
       }
}
}


Класс Terminal реализует интерфейс SerialPortEventListener, это подразумевает включение одного единственного метода public void serialEvent(SerialPortEvent event){}. Рассмотрим используемые нами методы класса SerialPort:

Итак, разберем по шагам, что происходит в конструкторе класса Terminal. Получив объект CommPortIdentifier, мы открываем порт, и преобразуем его к типу SerialPort:

serialPort = (SerialPort)
portId.open("TerminalApp", 2000);

после чего открываем входной и выходной потоки:

outputStream = serialPort.getOutputStream();
inputStream = serialPort.getInputStream();

регестрируем объект SerialPortEventListener и устанавливаем параметры порта:

serialPort.addEventListener(this);
serialPort.setSerialPortParams(9600,
                SerialPort.DATABITS_8,
                SerialPort.STOPBITS_1,
                SerialPort.PARITY_NONE);

Ну, и наконец, создаем новый поток, который в цикле, с интервалом в пять секунд, начинает писать в порт сообщения из массива messageString ={"ATI3\n","ATI1\n","AT\n"};

outputStream.write(messageString[i].getBytes());

Сообщения поступающие из COM порта на поможет прослушать метод serialEvent, который при наступлении события SerialPortEvent.DATA_AVAILABLE читает данные из входного потока.

Вот казалось бы и все, только осталась маленькая деталь. Заменим строку в конструкторе класса Terminal:

outputStream = serialPort.getOutputStream();

на

outputStream = new ConvertedOutputStream
          (serialPort.getOutputStream());

где класс ConvertedOutputStream выглядит следующим образом.

import java.io.OutputStream;
import java.io.IOException;

class ConvertedOutputStream extends OutputStream {
    OutputStream outstream;
  ConvertedOutputStream(OutputStream outstream) {
    this.outstream = outstream;
}
public void flush() throws IOException {
    outstream.flush();
}
    private int prev = 0;
public void write(int b) throws IOException {
    if (b == '\n') {
        if (prev != '\r')
        outstream.write('\r');
    } else if (b == '\r') {
        if (prev != '\n')
        outstream.write('\n');
    }
    prev = b;
    outstream.write(b);
}
}


Данный класс расширяет OutputStream, перегружая основной метод write(int b) и его понимание я оставляю на откуп читателям.

Таким образом, наше приложение вполне сформировано, если его запустить на выполнение, то мы увидим примерно следующее:

ATI3
Sportster 33600/Fax V10.0.23
OK
ATI1
7C60
OK
AT
OK

Модем корректно откликнулся на команды, следовательно, написанное нами приложение, работает правильно. Так что теперь, вооружившись полученными знаниями вы можете спокойно приступать к написанию аналога HyperTerminal :)). За дополнительными сведениями обращайтесь к литературе (см [1]).

Ресурсы

[an error occurred while processing this directive]
[an error occurred while processing this directive] ООО 'Кубикс' (www.qbix.ru), Санкт-Петербург.
< Вернуться на caйт :: Copyright © 1999 — 2010, IT • archiv.