Базы данныхИнтернетКомпьютерыОперационные системыПрограммированиеСетиСвязьРазное
Поиск по сайту:
Подпишись на рассылку:

Назад в раздел

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

div.main {margin-left: 20pt; margin-right: 20pt}
Доступ к COM порту из Java приложения Эта статья посвящена обзору пакета 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. Положите файл win32com.dll в директорию <jdk>jrebin . Положите архив comm.jar в директорию <jdk>jrelibext. Положите файл javax.comm.properties в <jdk>jrelib . Не изменяйте переменную 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: Переменные класса:

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 если порт используется другим приложением.

Таким образом, в методе 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 = {"ATn","ATI1n","ATI3n"}; 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:

public abstract InputStream getInputStream() throws IOException Возвращает поток InputStream. Это один единственный способ получить данные из порта. Если порт не поддерживает получение данных то данный метод вернет null. Метод наследуется от класса CommPort. public abstract OutputStream getOutputStream() throws IOException Возвращает поток OutputStream. Это один единственный способ послать данные в порт. Если порт не поддерживает посылку данных то данный метод вернет null. Метод наследуется от класса CommPort. public void close() Метод закрывает порт. Приложение может вызвать метод close когда оно закончило работу с портом. Метод наследуется от класса CommPort. public abstract void notifyOnDataAvailable(boolean enable) Когда данные будут доступны в входном буфере, будут послано оповещение listener который зарегестрирован методом addEventListener. Сообщение будет сгенерировано один раз, когда новые данные поступят в последовательный порт. Параметры: enable - true: оповещение включено. false: оповещение выключено. public abstract void addEventListener(SerialPortEventListener lsnr) throws TooManyListenersException Регестрирует объект SerialPortEventListener для прослушивания SerialEvent-s.

Итак, разберем по шагам, что происходит в конструкторе класса 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 ={"ATI3n","ATI1n","ATn"}; 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]).

Ссылки: http://java.sun.com/products/javacomm/javadocs/packages.htmlЭто полное описание API функций пакета javax.com http://java.sun.com/products/javacomm/index.htmlЗдесь находится пакет javax.comm и инструкции по его установке. ООО "Кубикс" (www.qbix.ru), Санкт-Петербург.

Дата последнего обновления: 6 августа 2000 г. Автор Владислав Каменский


  • Главная
  • Новости
  • Новинки
  • Скрипты
  • Форум
  • Ссылки
  • О сайте




  • Emanual.ru – это сайт, посвящённый всем значимым событиям в IT-индустрии: новейшие разработки, уникальные методы и горячие новости! Тонны информации, полезной как для обычных пользователей, так и для самых продвинутых программистов! Интересные обсуждения на актуальные темы и огромная аудитория, которая может быть интересна широкому кругу рекламодателей. У нас вы узнаете всё о компьютерах, базах данных, операционных системах, сетях, инфраструктурах, связях и программированию на популярных языках!
     Copyright © 2001-2024
    Реклама на сайте