[Ubnutu] RXTX で PC-OP-RS1 を操作する

スポンサーリンク

環境

Ubuntu 12.04.1 (64bit)
Oracle JDK 7

前準備

[Ubuntu] Oracle JDK 7, JDK 6" href="http://hirooka.pro/?p=494" target="_blank">Oracle JDK 7 の導入</a> <a title="[Ubuntu] RXTX" href="http://hirooka.pro/?p=665" target="_blank">RXTX の導入</a> <a title="[Ubuntu] PC-OP-RS1" href="http://hirooka.pro/?p=669" target="_blank">PC-OP-RS1 の導入</a> <h1>動作テストプログラム</h1> PC-OP-RS1 は,2006年に発売された製品のようで,挙動については既に解析例が多数ウェブに掲載されています. 動作テストとして,シリアルポートの設定をして PC-OP-RS1 の赤色 LED を 1 回点滅させてみます. Java から PC-OP-RS1 へ 0×69 を送ると 0x4f が返ってきます. その際に PC-OP-RS1 本体の赤色 LED が 1 回点滅します. 0×69 を送ってイベントリスナで受信を待ち受け,0x4f を受信するとシリアル通信を閉じる,というプログラムを作成してみます. <h2>リスナ</h2> [java] package com.example.pc_op_rs1_tester; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.TooManyListenersException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import gnu.io.CommPortIdentifier; import gnu.io.NoSuchPortException; import gnu.io.PortInUseException; import gnu.io.SerialPort; import gnu.io.SerialPortEvent; import gnu.io.SerialPortEventListener; import gnu.io.UnsupportedCommOperationException; public class PcOpRs1Tester implements SerialPortEventListener{ private static Logger log = LoggerFactory.getLogger(PcOpRs1Tester.class); private String deviceName; private SerialPort port; private InputStream is; private OutputStream os; PcOpRs1Tester(String _deviceName){ deviceName = _deviceName; } boolean openSerialPort(){ try { CommPortIdentifier portID = CommPortIdentifier.getPortIdentifier(deviceName); try { port = (SerialPort)portID.open("PC-OP-RS1 Test Application", 5000); log.info("You can use " + deviceName + " now!"); } catch (PortInUseException e) { log.info("[openSerialPort()] " + deviceName + " is used by other application now."); e.printStackTrace(); return false; } } catch (NoSuchPortException e) { log.info("[openSerialPort()] " + deviceName + " does not exist."); e.printStackTrace(); return false; } return true; } boolean setSerialPort(){ try { port.setSerialPortParams( 115200, // [bps] SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE ); port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE); try { port.addEventListener(this); } catch (TooManyListenersException e) { log.info(deviceName + ":setSerialPort():TooManyListenersException"); e.printStackTrace(); return false; } port.notifyOnDataAvailable(true); try { is = port.getInputStream(); os = port.getOutputStream(); } catch (IOException e) { log.info(deviceName + ":setSerialPort():IOException"); e.printStackTrace(); return false; } log.info(deviceName + " : setSerialPort() is OK!"); } catch (UnsupportedCommOperationException e) { log.info(deviceName + ":UnsupportedCommOperationException"); e.printStackTrace(); return false; } return true; } private void closePort(){ port.close(); log.info(deviceName + " is closed"); } public void send0x69(){ log.info(deviceName + " : PC-OP-RS1 sent 0x69!"); byte b = 0x69; try { os.write(b); os.flush(); os.close(); } catch (IOException e) { log.info(deviceName + ": send0x69:IOException"); e.printStackTrace(); } } public void serialEvent(SerialPortEvent event) { if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) { read(); } } private void read(){ byte[] in = new byte[1024]; int len; try { while((len = is.read(in)) != -1){ if(String.format("%02x", in[0]).toUpperCase().equals("4F") && (len == 1)){ log.info(deviceName + " : PC-OP-RS1 received 0x4F"); break; } } is.close(); } catch (IOException e) { log.info(deviceName + ": read():IOException"); e.printStackTrace(); } finally { closePort(); } } } // class

メイン

package com.example.pc_op_rs1_tester;

import java.util.Enumeration;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;

public class RunPcOpRs1Tester {

	private static Logger log = LoggerFactory.getLogger(RunPcOpRs1Tester.class);

	public static void main(String[] args) {

		if(args.length == 0){
			log.info("You MUST set deviceName!");
			System.exit(-1);
		}else if(args.length > 1){
			log.info("Too many args[]!");
			System.exit(-1);
		}

		String deviceName = args[0];
		//String deviceName = "/dev/ttyUSB0";
		log.info("[deviceName] " + deviceName);

		CommPortIdentifier portID;
		@SuppressWarnings("unused")
		SerialPort port;

		@SuppressWarnings("unchecked")
		Enumeration portList = CommPortIdentifier.getPortIdentifiers();
		while(portList.hasMoreElements()){
			portID = (CommPortIdentifier)portList.nextElement();
			log.info("[portID.getName()] " + portID.getName());

			if(portID.getPortType() == CommPortIdentifier.PORT_SERIAL){
				log.info("[portID.getPortType()] " + deviceName + " is Serial device.");

				if(portID.getName().equals(deviceName)){

					if(portID.isCurrentlyOwned()){
						log.info("[portID.isCurrentlyOwned()] " + deviceName + " is used by other aplication now.");
						break;
					}else{
						log.info("[portID.isCurrentlyOwned()] You can use " + deviceName);

						PcOpRs1Tester rxtx = new PcOpRs1Tester(deviceName);

						if(rxtx.openSerialPort()){
							if(rxtx.setSerialPort()){
								rxtx.send0x69();
							}else{
								log.info("[rxtx.openSerialPort()] " + deviceName + ": rxtx.setSerialPort()");
								break;
							}
						}else{
							log.info("[rxtx.openSerialPort()] " + deviceName + ": rxtx.openSerialPort()");
							break;
						}
					}

				}else{
					log.info(portID.getName() + " is NOT match " + deviceName);
				}

			}else if(portID.getPortType() == CommPortIdentifier.PORT_PARALLEL){
				log.info("[portID.getPortType()] " + deviceName + " is Parallel device.");
				break;
			}else{
				log.info("[portID.getPortType()] " + deviceName + " is Unknown device.");
				break;
			}

		} // while()

	} // main()

} // class

学習プログラム

PC-OP-RS1 で赤外線リモコンの信号を学習させてみます.

0×72 を送信すると 0×59 が返ってきてリモコン信号の受信待ちになります.
そして,PC-OP-RS1 の受光部にリモコン信号を送ってやると,0×53 + リモコン信号(240Byte) + 0×45 が送られてきます.
PC-OP-RS1 から送られてくるリモコン信号は 240Byte 固定であり,リモコン信号が 240Byte 未満の場合は末尾は 0 でパディングされ,240Byte を超える場合は学習できないようです.
例えばテレビのリモコンのように単純な信号であれば 240Byte を超えることはないようですが,エアコンのリモコンの様に多くの情報を送る場合,機種によっては 240Byte を超えてしまい,うまく学習させられないこともあるようです.

0×72 を送ってイベントリスナで受信を待ち受け,0×59 を受信するとリモコン信号の受信待ちになり,リモコン信号を受信して最後のデータが 0×45 であればシリアル通信を閉じる,というプログラムを作成してみます.

リスナ

package com.example.pc_op_rs1_memory;

import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.TooManyListenersException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PcOpRs1Memory implements SerialPortEventListener{

	private static Logger log = LoggerFactory.getLogger(PcOpRs1Memory.class);
	static final String SEPARATOR = System.getProperty("file.separator");

	private String deviceName;
	private SerialPort port;

	private InputStream is;
	private OutputStream os;

	private boolean flag0x72;

	private String outputPath;

	PcOpRs1Memory(String _deviceName, String _outputPath){
		deviceName = _deviceName;
		outputPath = _outputPath;
		flag0x72 = false;
	}

	boolean openSerialPort(){
		try {
			CommPortIdentifier portID = CommPortIdentifier.getPortIdentifier(deviceName);
			try {
				port = (SerialPort)portID.open("PC-OP-RS1 Test Application", 5000);
				log.info("You can use " + deviceName + " now!");
			} catch (PortInUseException e) {
				log.info("[openSerialPort()] " + deviceName + " is used by other application now.");
				e.printStackTrace();
				return false;
			}

		} catch (NoSuchPortException e) {
			log.info("[openSerialPort()] " + deviceName + " does not exist.");
			e.printStackTrace();
			return false;
		}
		return true;
	} // openSerialPort()

	boolean setSerialPort(){
		try {
			port.setSerialPortParams(
					115200,                 // [bps]
					SerialPort.DATABITS_8,
					SerialPort.STOPBITS_1,
					SerialPort.PARITY_NONE
			);
			port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);

			try {
				port.addEventListener(this);
			} catch (TooManyListenersException e) {
				log.info(deviceName + ":setSerialPort():TooManyListenersException");
				e.printStackTrace();
				return false;
			}
			port.notifyOnDataAvailable(true);

			try {
				is = port.getInputStream();
				os = port.getOutputStream();
			} catch (IOException e) {
				log.info(deviceName + ":setSerialPort():IOException");
				e.printStackTrace();
				return false;
			}
			log.info(deviceName + " : setSerialPort() is OK!");
		} catch (UnsupportedCommOperationException e) {
			log.info(deviceName + ":UnsupportedCommOperationException");
			e.printStackTrace();
			return false;
		}
		return true;
	} // setSerialPort()

	private void closePort(){
		port.close();
		log.info(deviceName + " is closed");
	}

	public void send0x72(){
		log.info(deviceName + " : PC-OP-RS1 sent 0x72!");
		byte b = 0x72;
		try {
			os.write(b);
			os.flush();
			os.close();
			flag0x72 = true;
		} catch (IOException e) {
			log.info(deviceName + ": send0x72:IOException");
			e.printStackTrace();
			System.exit(-1);
		}
	} // send0x72(){

	public void serialEvent(SerialPortEvent event) {
		if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
			read();
		}
	}

	private void read(){
		FileWriter fw = null;
		BufferedWriter bw = null;
		if(flag0x72){
			try {
				fw = new FileWriter(outputPath);
				bw = new BufferedWriter(fw);
			} catch (IOException e) {
				log.info(deviceName + ": FileWriter of read():IOException");
				e.printStackTrace();
				System.exit(-1);
			}
		}
		byte[] in = new byte[1024];
		int len;
		try {
			while((len = is.read(in)) != -1){
				for(int i = 0; i < len; i++){
					if(flag0x72){
						if((!(String.format("%02x", in[0]).equals("59") && (len == 1))) && (!(String.format("%02x", in[0]).equals("45") && (len == 1)))){
							System.out.print(String.format("%02x", in[i]));
						}
						bw.write(String.format("%02x", in[i]));
					}
				}
				if(String.format("%02x", in[0]).equals("59") && (len == 1)){
					//System.out.println("receive 0x59");
					//System.out.println("SEND Remocon Signal!");
					log.info(deviceName + " : PC-OP-RS1 send 0x59!");
					System.out.println("Please send remocon signal!");
				}
				if(String.format("%02x", in[0]).equals("45") && (len == 1)){
					System.out.println();
					//System.out.println("receive 0x45");
					log.info(deviceName + " : PC-OP-RS1 receive 0x45!");
					break;
				}
			}
			if(flag0x72){
				bw.close();
				fw.close();
			}
			is.close();
		} catch (IOException e) {
			log.info(deviceName + ": read():IOException");
			e.printStackTrace();
		} finally {
			closePort();
		}
	} // read()

} // class

メイン

package com.example.pc_op_rs1_memory;

import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;

import java.util.Enumeration;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RunPcOpRs1Memory {

	private static Logger log = LoggerFactory.getLogger(RunPcOpRs1Memory.class);
	static final String SEPARATOR = System.getProperty("file.separator");

	public static void main(String[] args) {

		if(args.length == 0){
			log.info("You MUST set deviceName!");
			System.exit(-1);
		}else if(args.length > 2){
			log.info("Too many args[]!");
			System.exit(-1);
		}

		String deviceName = args[0];
		//String deviceName = "/dev/ttyUSB0";
		log.info("[deviceName] " + deviceName);

		String outputPath = args[1];
		log.info("[outputPath] " + outputPath);

		CommPortIdentifier portID;
		@SuppressWarnings("unused")
		SerialPort port;

		@SuppressWarnings("unchecked")
		Enumeration portList = CommPortIdentifier.getPortIdentifiers();
		while(portList.hasMoreElements()){
			portID = (CommPortIdentifier)portList.nextElement();
			log.info("[portID.getName()] " + portID.getName());

			if(portID.getPortType() == CommPortIdentifier.PORT_SERIAL){
				log.info("[portID.getPortType()] " + deviceName + " is Serial device.");

				if(portID.getName().equals(deviceName)){

					if(portID.isCurrentlyOwned()){
						log.info("[portID.isCurrentlyOwned()] " + deviceName + " is used by other aplication now.");
						break;
					}else{
						log.info("[portID.isCurrentlyOwned()] You can use " + deviceName);

						PcOpRs1Memory rxtx = new PcOpRs1Memory(deviceName, outputPath);

						if(rxtx.openSerialPort()){
							if(rxtx.setSerialPort()){
								rxtx.send0x72();
							}else{
								log.info(deviceName + ": rxtx.setSerialPort()");
								break;
							}
						}else{
							log.info(deviceName + ": rxtx.openSerialPort()");
							break;
						}
					}

				}else{
					log.info(portID.getName() + " is NOT match " + deviceName);
				}

			}else if(portID.getPortType() == CommPortIdentifier.PORT_PARALLEL){
				log.info("[portID.getPortType()] " + deviceName + " is Parallel device.");
				break;
			}else{
				log.info("[portID.getPortType()] " + deviceName + " is Unknown device.");
				break;
			}

		} // while()

	} // main()

} // class

実際に実行してみます.
アプリケーションを実行すると,ホームディレクトリ直下に receive.txt が生成されます.
0×59 + 0×53 + (リモコン信号 240Byte) + 0×45 を 【5953(リモコン信号480文字)45】 という 16 進数表記の文字列 (ただし,0xは省略) に変換しているので,receive.txt のサイズは,実際に受信する 243Byte の倍の 486Byte になります.

下記は,自宅のエアコンの信号を学習させてみた結果の一例です.
240Byte に収まっているようです.

send 0x72
receive 0x59
SEND Remocon Signal!
53ffffffffff1f00000000003e00800f7c00801f00e0031ff800003ff8c10700f0810f7c00801f00e0031f00c0073f00c00700f001007c00801f7c00001f00c00700f8c1073ef0810f00f0831f7c00001f00c00700f8c1073ef0810f7cf0831f7c00001f00c00700f801003e00800f000000000080ffffffffff0700000000800f00e0031f00e00700f8c0073e00800f7ef003007ce0031f00e00700f8c00700f0810f00f003007c00001f00e0073f00c00700f001007ef0830f7ce00300f8e0073f00c00700f001007ef0830f7ce0031ff8e0073f00c00700f001007e00800f00e0030000000000000000000000000000
receive 0x45
close

送信プログラム

学習リモコンで学習させた信号を送信してみます.
0×74 を送信すると 0×59 が返ってきます.
それに対してさらに 0×31 を送信します.

0×31 は、PC-OP-RS1 の A 端子に接続した発光部の中で,黄色いシールが貼られている発光部から赤外線信号を出してください,という合図です.
PC-OP-RS1 には 4ch の発光部を持っていますが,

1ch 0×31 A端子に接続された黄色シールの発光部
2ch 0×32 A端子に接続された無印の発光部
3ch 0×33 B端子に接続された黄色シールの発光部
4ch 0×44 B端子に接続された無印の発光部

となるようです.

0×31 を送信した後、0×59 が返ってきます.
それに対して学習した信号 (240Byte) を送信します.
送信後,0×45 が返ってくればシリアル通信を閉じます.

リスナ

package com.example.pc_op_rs1_sender;

import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.TooManyListenersException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PcOpRs1Sender implements SerialPortEventListener{
	private static Logger log = LoggerFactory.getLogger(PcOpRs1Sender.class);
	static final String SEPARATOR = System.getProperty("file.separator");

	private String deviceName;
	private SerialPort port;

	private InputStream is;
	private OutputStream os;

	@SuppressWarnings("unused")
	private boolean flag0x74;
	private boolean flag0x31;

	private String signalPath;

	PcOpRs1Sender(String _deviceName, String _signalPath){
		deviceName = _deviceName;
		signalPath = _signalPath;
		flag0x74 = false;
		flag0x31 = false;
	}

	boolean openSerialPort(){
		try {
			CommPortIdentifier portID = CommPortIdentifier.getPortIdentifier(deviceName);
			try {
				port = (SerialPort)portID.open("PC-OP-RS1 Test Application", 5000);
				log.info("You can use " + deviceName + " now!");
			} catch (PortInUseException e) {
				log.info("[openSerialPort()] " + deviceName + " is used by other application now.");
				e.printStackTrace();
				return false;
			}
		} catch (NoSuchPortException e) {
			log.info("[openSerialPort()] " + deviceName + " does not exist.");
			e.printStackTrace();
			return false;
		}
		return true;
	} // openSerialPort()

	boolean setSerialPort(){
		try {
			port.setSerialPortParams(
					115200,                 // [bps]
					SerialPort.DATABITS_8,
					SerialPort.STOPBITS_1,
					SerialPort.PARITY_NONE
			);
			port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
			try {
				port.addEventListener(this);
			} catch (TooManyListenersException e) {
				log.info(deviceName + ":setSerialPort():TooManyListenersException");
				e.printStackTrace();
				return false;
			}
			port.notifyOnDataAvailable(true);
			try {
				is = port.getInputStream();
				os = port.getOutputStream();
			} catch (IOException e) {
				log.info(deviceName + ":setSerialPort():IOException");
				e.printStackTrace();
				return false;
			}
			log.info(deviceName + " : setSerialPort() is OK!");
		} catch (UnsupportedCommOperationException e) {
			log.info(deviceName + ":UnsupportedCommOperationException");
			e.printStackTrace();
			return false;
		}
		return true;
	} // setSerialPort()

	private void closePort(){
		port.close();
		log.info(deviceName + " is closed");
	}

	public void send0x74(){
		log.info(deviceName + " : PC-OP-RS1 sent 0x74!");
		byte b = 0x74;
		try {
			os.write(b);
			os.flush();
			os.close();
			flag0x74 = true;
		} catch (IOException e) {
			log.info(deviceName + ": send0x74:IOException");
			e.printStackTrace();
			System.exit(-1);
		}
	} // send0x74(){

	public void send0x31(){
		log.info(deviceName + " : PC-OP-RS1 sent 0x31!");
		byte b = 0x31;
		try {
			os.write(b);
			os.flush();
			os.close();
			flag0x31 = true;
		} catch (IOException e) {
			log.info(deviceName + ": send0x31:IOException");
			e.printStackTrace();
			System.exit(-1);
		}
	} // send0x31(){

	public void sendSignal(){
		log.info(deviceName + " : PC-OP-RS1 sends signal");
		byte[] out = new byte[240];
		byte b;
		try {
			FileReader fr = new FileReader(signalPath);
			BufferedReader br = new BufferedReader(fr);
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			String str;
			while((str = br.readLine()) != null){
				//System.out.println(str);
				int i = 0;
				while(i < str.length()){
					String tmpStr = str.substring(i, i+2);
					int tmpInt = Integer.parseInt(tmpStr, 16);
					b = (byte)tmpInt;
					baos.write(b);
					i = i + 2;
				}
			}
			br.close();
			fr.close();
			out = baos.toByteArray();
			baos.close();
			for(int i = 0; i < out.length; i++){
				if((i!=0) && (i!=1) && (i!=(out.length-1))){
					os.write(out[i]);
					System.out.print(String.format("%02x", out[i]));
				}
			}
			os.flush();
			os.close();
		} catch(FileNotFoundException e){
			log.info(deviceName + ": sendSignal:FileNotFoundException");
			e.printStackTrace();
			System.exit(-1);
		}catch(IOException e){
			log.info(deviceName + ": sendSignal:IOException");
			e.printStackTrace();
			System.exit(-1);
		}
	} // sendSignal()

	public void serialEvent(SerialPortEvent event) {
		if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
			read();
		}
	}

	private void read(){
		byte[] in = new byte[1024];
		int len;
		try {
			while((len = is.read(in)) != -1){
				if(String.format("%02x", in[0]).equals("59") && (len == 1)){
					log.info(deviceName + " : PC-OP-RS1 receive 0x59!");
						if(!flag0x31){
							send0x31();
						}else{
							sendSignal();
						}
				}
				if(String.format("%02x", in[0]).equals("45") && (len == 1)){
					System.out.println();
					log.info(deviceName + " : PC-OP-RS1 receive 0x45!");
					break;
				}
			}
			is.close();
		} catch (IOException e) {
			log.info(deviceName + ": read():IOException");
			e.printStackTrace();
		} finally {
			closePort();
		}
	} // read()

} // class

メイン

package com.example.pc_op_rs1_sender;

import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;

import java.util.Enumeration;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RunPcOpRs1Sender {

	private static Logger log = LoggerFactory.getLogger(RunPcOpRs1Sender.class);
	static final String SEPARATOR = System.getProperty("file.separator");

	public static void main(String[] args) {

		if(args.length == 0){
			log.info("You MUST set deviceName!");
			System.exit(-1);
		}else if(args.length > 2){
			log.info("Too many args[]!");
			System.exit(-1);
		}

		String deviceName = args[0];
		//String deviceName = "/dev/ttyUSB0";
		log.info("[deviceName] " + deviceName);

		String signalPath = args[1];
		log.info("[signalPath] " + signalPath);

		CommPortIdentifier portID;
		@SuppressWarnings("unused")
		SerialPort port;

		@SuppressWarnings("unchecked")
		Enumeration portList = CommPortIdentifier.getPortIdentifiers();
		while(portList.hasMoreElements()){
			portID = (CommPortIdentifier)portList.nextElement();
			log.info("[portID.getName()] " + portID.getName());

			if(portID.getPortType() == CommPortIdentifier.PORT_SERIAL){
				log.info("[portID.getPortType()] " + deviceName + " is Serial device.");

				if(portID.getName().equals(deviceName)){

					if(portID.isCurrentlyOwned()){
						log.info("[portID.isCurrentlyOwned()] " + deviceName + " is used by other aplication now.");
						break;
					}else{
						log.info("[portID.isCurrentlyOwned()] You can use " + deviceName);

						PcOpRs1Sender rxtx = new PcOpRs1Sender(deviceName, signalPath);

						if(rxtx.openSerialPort()){
							if(rxtx.setSerialPort()){
								rxtx.send0x74();
							}else{
								log.info(deviceName + ": rxtx.setSerialPort()");
								break;
							}
						}else{
							log.info(deviceName + ": rxtx.openSerialPort()");
							break;
						}
					}

				}else{
					log.info(portID.getName() + " is NOT match " + deviceName);
				}

			}else if(portID.getPortType() == CommPortIdentifier.PORT_PARALLEL){
				log.info("[portID.getPortType()] " + deviceName + " is Parallel device.");
				break;
			}else{
				log.info("[portID.getPortType()] " + deviceName + " is Unknown device.");
				break;
			}

		} // while()

	} // main()

} // class

実際に実行してみます.
0×74 を送信し,0×59 を受信した後に 0×31 を送信し,再度 0×59 を受信した後に学習結果 receive.txt を読み込み,240Byte の信号を送信します.(先頭の 5953 と末尾の 45 は除外する)
その後,0×45 を受信したところでシリアル通信を閉じます.

学習させた自宅のエアコンの信号 (電源OFF) を PC-OP-RS1 からエアコン本体の受光部に向けて送信した結果の一例です.

send 0x74
receive 0x59
send 0x31
receive 0x59
send Signal
ffffffffff1f00000000003e00800f7c00801f00e0031ff800003ff8c10700f0810f7c00801f00e0031f00c0073f00c00700f001007c00801f7c00001f00c00700f8c1073ef0810f00f0831f7c00001f00c00700f8c1073ef0810f7cf0831f7c00001f00c00700f801003e00800f000000000080ffffffffff0700000000800f00e0031f00e00700f8c0073e00800f7ef003007ce0031f00e00700f8c00700f0810f00f003007c00001f00e0073f00c00700f001007ef0830f7ce00300f8e0073f00c00700f001007ef0830f7ce0031ff8e0073f00c00700f001007e00800f00e0030000000000000000000000000000
receive 0x45
close

PC-OP-RS1 でエアコンの電源を OFF させることができました.

同様にエアコンを電源 OFF 状態から ON 状態にする信号を学習させることで,エアコンの電源を ON させることができました.

一般的に,エアコンの電源 ON/OFF ボタンは同一ボタンであることがほとんどだと思いますが,OFF から ON の場合と ON から OFF の場合とでは,同じボタンを押しても送信される信号は異なるので注意が必要です.