본문 바로가기

컴퓨터 정보

자바 시리얼통신(Java Serial) - 예전 글 복구

반응형

* 예전에 삭제된 페이지 복구 - 자바 시리얼통신(Java Serial)

자바 시리얼통신(Java Communications API)
자바 시리얼통신(java Serial), Communication API, javacomm20-win32.zip

자바 시리얼통신(Java Serial)

자바에서 RS-232c나 패러럴(parallel)포트에 접근하기 위해서는 Communication API을 사용해야 합니다. Communication API은 자바 J2SE에서 제공하는 표준 API가 아니므로, 추가적으로 다운로드 받아서 설치 해주셔야 합니다.

참고로, 자바의 Communication API 공식 사이트 주소는 다음과 같습니다.

http://java.sun.com/products/javacomm/index.html

 

javacomm20-win32.zip

 

먼저 Java Communications API를 다운로드하고 압축을 풉니다.(첨부파일)

comm.jar를 클래스패스에 포함하지 말고 공유라이브러리 파일을 bin 디렉터리로 복사하고 javax.comm.properties 파일을 런타임 환경의 lib로 복사합니다.

윈도우 Java 2 SDK 버전 1.3에서 다음과 같습니다.

 

copy comm.jar \jdk1.3\jre\lib\ext

copy win32com.dll \jdk1.3\bin

copy javax.comm.properties \jdk1.3\jre\lib

 

설정이 끝나면 Java Communications API 클래스는 javax.comm 패키지로 사용 가능합니다. 이 패키지에서 핵심이 되는 클래스는 CommPortIdentifier와 CommPort 입니다. CommPortIdentifier는 설치된 CommPort 객체를 찾는 데 사용되며, 각각의 CommPort 객체와 통신할 수 있습니다.

// Rs232c.java

import java.io.*;
import javax.comm.*;
public class Rs232c {
    public static void main( String arg[] ) {
        try {
            CommPortIdentifier ports = CommPortIdentifier.getPortIdentifier( "COM1" );
            SerialPort port = ( SerialPort )ports.open( "RS232C", 1000 );
            port.setSerialPortParams( 9600,
                SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE );
            port.setFlowControlMode( SerialPort.FLOWCONTROL_NONE );
            OutputStream out = port.getOutputStream();
            String msg = "Hello";
            out.write( msg.getBytes() );
            out.flush();
            out.close();
            port.close();
        }
        catch( Exception e ) {
            System.out.println( "Error:" + e.getMessage() );
        }
    }
}

다음 코드는 사용가능한 포트의 이름과 타입을 가져오는 예제입니다.

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

public class ListPorts { 
	public static void main(String args[]) 
	{ 
		Enumeration ports = CommPortIdentifier.getPortIdentifiers(); 
		while (ports.hasMoreElements()) 
		{ 
			CommPortIdentifier port = (CommPortIdentifier)ports.nextElement(); 
			String type; 
			switch (port.getPortType()) 
			{ 
				case CommPortIdentifier.PORT_PARALLEL: 
					type = "Parallel"; 
				break; 
				case CommPortIdentifier.PORT_SERIAL: 
					type = "Serial"; 
				break; 
				default: /// Shouldn't happen 
					type = "Unknown"; 
				break; 
			} 
			System.out.println(port.getName() + ": " + type); 
		} 
	} 
} 

ListPorts는 다음과 비슷한 결과를 출력합니다.

COM1: Serial

COM2: Serial

LPT1: Parallel

LPT2: Parallel

자바 시리얼통신 예제(Java Serial) - 출처모름

CommPortIdentifier에서 포트 Enumeration을 돌면서 포트의 정보를 얻어 올 수도 있다. getPortIdentifier() 메소드에 포트의 이름을 인수로 전달해서(예 LPT1) 이 작업을 할 수 있다.

반환되는 값은 포트 식별자이고, 포트가 존재하지 않으면 javax.comm.NoSuchPortException으로 예외처리 한다.

// Get port

CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier(portname); 포트를 읽거나 쓰기 위해서 open() 메소드를 사용해야 한다. open() 메소드는 포트 소유자 이름과 밀리세컨드 단위로 타임아웃 시간이 필요하다.

// Open port

// Open requires a owner name and timeout

CommPort port = portId.open("Application Name", 30000); 포트를 열면 소켓통신과 같이 읽기/쓰기가 가능하다. CommPort의 getInputStream() 메소드로 InputStream을 사용하고, getOutputStream()를 통해서 OutputStream을 얻을 수 있다.

// Setup output

OutputStream os = port.getOutputStream(); BufferedOutputStream bos = new BufferedOutputStream(os); 이제 COMM API를 이용해서 파일을 출력해 보자. 일단 프린터 포트를 찾고, 그것을 열어서 OutputStream을 얻어온 후 파일내용을 보내면 된다.

다음 예제는 그 과정을 보여준다. sample.ps라는 PostScript 파일을 출력한다. sample.ps을 먼저 만들고, 작업이 끝난 후에는 포트와 스트림을 닫아 준다.

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

public class PrintFile { 
	public static void main(String args[]) throws Exception { 
		if (args.length != 2) { 
			System.err.println("usage : java PrintFile port file"); 
			System.err.println("sample: java PrintFile LPT1 sample.ps"); 
			System.exit(-1); 
		} 

		String portname = args[0]; 
		String filename = args[1]; 

		// Get port 
		CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier(portname); 


		// Open port 
		// Open requires a owner name and timeout 
		CommPort port = portId.open("Application Name", 30000); 

		// Setup reading from file 
		FileReader fr = new FileReader(filename); 
		BufferedReader br = new BufferedReader(fr); 

		// Setup output 
		OutputStream os = port.getOutputStream(); 
		BufferedOutputStream bos = new BufferedOutputStream(os); 

		int c; 
		while ((c = br.read()) != -1) { 
			bos.write(c); 
		} 

		// Close 
		bos.close(); 
		br.close(); 
		port.close(); 
	} 
} 

////////////////////////////////////////////////////////////////////////

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

public class SerialEcho implements Runnable, SerialPortEventListener {
	static CommPortIdentifier portId;
	static Enumeration portList;

	BufferedReader br;
	BufferedWriter bw;
	String echoMsg;
	SerialPort serialPort;
	Thread readThread;

	public static void main(String[] args) {

		// 시스템의 모든 포트 리스트를 가져옴.
		portList = CommPortIdentifier.getPortIdentifiers();

		while (portList.hasMoreElements()) {
			portId = (CommPortIdentifier) portList.nextElement();

			// 현재 포트타입이 시리얼 포트일 경우
			if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {

				// MS-windows에서 시리얼 포트 이름은 “COM1”,”COM2”…
				if (portId.getName().equals("COM1")) { 
					// if (portId.getName().equals("/dev/term/a")) { // Solaris
					// 시리얼 통신을 위한 포트 생성
					SerialEcho reader = new SerialEcho();
				}
			}
		}
	}

	public SerialEcho() {
		try{
			serialPort = (SerialPort) portId.open("SerialEcho", 2000);
        }  
		catch (PortInUseException e) {}

		try {
			br = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
            bw = new BufferedWriter(new OutputStreamWriter(serialPort.getOutputStream()));
        }  
		catch (IOException e) {}
		
        try {
			// 시리얼 포트에 데이터가 수신되기를 기다림.
			serialPort.addEventListener(this);
        } 
		catch (TooManyListenersException e) {}
       
		// input data가 들어오면 수신 통보
        serialPort.notifyOnDataAvailable(true);
		
		try{
            serialPort.setSerialPortParams(19200,       // Baud Rate
            SerialPort.DATABITS_8,                		// Data Bits
            SerialPort.STOPBITS_1,                		// Stop Bits
            SerialPort.PARITY_NONE);             		// Parity
        }  
		catch (UnsupportedCommOperationException e) {}
        
		readThread = new Thread(this);
        readThread.start();
	}
	
	
	public void run() {
		try {
			Thread.sleep(20000);
		}  
		catch (InterruptedException e) {}
	}
 
	public void serialEvent(SerialPortEvent event) {
		switch(event.getEventType()) {
			case SerialPortEvent.BI:      	// Break interrupt
			case SerialPortEvent.OE:     	// Overrun error
			case SerialPortEvent.FE:      	// Framing error
			case SerialPortEvent.PE:     	// Parity error. 
			case SerialPortEvent.CD:     	// Carrier detect
			case SerialPortEvent.CTS:  		// Clear to send
			case SerialPortEvent.DSR:   	// Data set ready
			case SerialPortEvent.RI:      	// Ring indicator. 
			case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
				break;             			// Output buffer is empty
			// Data available at the serial port. 
			case SerialPortEvent.DATA_AVAILABLE:
				byte[] readBuffer = new byte[20];
				try{
					while(true){
						echoMsg = br.readLine();
						System.out.println("Echo: " + echoMsg);
						bw.write(echoMsg,0,echoMsg.length());
						bw.newLine();
						bw.flush();
					}                                
				}
				catch (IOException e) {}
				break;
		}
	}
} 
반응형