purejavacommを利用したシリアル通信サンプル

# はじめに

先日、"[Javaのシリアル通信ライブラリRXTXの課題と代替調査](https://qiita.com/kyosho/items/fc0c40458385c7d98232)"で紹介した"[PureJavaComm](http://www.sparetimelabs.com/purejavacomm/purejavacomm.php)"のサンプルを紹介します。
実際は"[PureJavaComm](http://www.sparetimelabs.com/purejavacomm/purejavacomm.php)"に加えて、"[netty-transport-purejavacomm](https://github.com/steveturner/netty-transport-purejavacomm)"も利用しています。

# サンプル
## maven
pom.xmlにpurejavacommを追加します。
また、"[netty-transport-purejavacomm](https://github.com/steveturner/netty-transport-purejavacomm)"はコピペして使っています。

```xml:pom.xml
...
	<dependencies>
		<dependency>
			<groupId>io.netty</groupId>
			<artifactId>netty-all</artifactId>
		</dependency>

		<!-- https://mvnrepository.com/artifact/com.github.purejavacomm/purejavacomm -->
		<dependency>
			<groupId>com.github.purejavacomm</groupId>
			<artifactId>purejavacomm</artifactId>
			<version>1.0.2.RELEASE</version>
		</dependency>
	</dependencies>
...
```

## Javaソース
今回は単純にCOM5に接続して、テキストを受信し続けるサンプルを作成しています。
COM5には、手持ちのMONOWireless社のTWE-Lite-USBを利用しました。

```java:PureJavaCommClient.java
package net.kyosho.serial.pjc;

import java.util.Enumeration;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.oio.OioEventLoopGroup;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import purejavacomm.CommPortIdentifier;

public final class PureJavaCommClient {

	public static void main(String[] args) throws Exception {
		CommPortIdentifier portid = null;
		Enumeration<CommPortIdentifier> e = CommPortIdentifier.getPortIdentifiers();
		while (e.hasMoreElements()) {
			portid = (CommPortIdentifier) e.nextElement();
			System.out.println("found " + portid.getName());
		}
		EventLoopGroup group = new OioEventLoopGroup();
		try {
			Bootstrap b = new Bootstrap();
			b.group(group).channel(PureJavaCommChannel.class).handler(new ChannelInitializer<PureJavaCommChannel>() {
				@Override
				public void initChannel(PureJavaCommChannel ch) throws Exception {
					ch.config().setBaudrate(115200).setParitybit(Paritybit.NONE).setStopbits(Stopbits.STOPBITS_1);
					ch.pipeline().addLast(new LineBasedFrameDecoder(32768), new StringEncoder(), new StringDecoder(),
							new PureJavaCommClientHandler());
				}
			});

			ChannelFuture f = b.connect(new PureJavaCommDeviceAddress("COM5")).sync();

			f.channel().closeFuture().sync();
		} finally {
			group.shutdownGracefully();
		}
	}

	private PureJavaCommClient() {
	}
}
```

```java:PureJavaCommClientHandler.java
package net.kyosho.serial.pjc;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

public class PureJavaCommClientHandler extends SimpleChannelInboundHandler<String> {

	@Override
	public void channelActive(ChannelHandlerContext ctx) {
		ctx.writeAndFlush("AT\n");
	}

	@Override
	public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
		if ("OK".equals(msg)) {
			System.out.println("Serial port responded to AT");
		} else {
			System.out.println("Serial port responded with not-OK: " + msg);
		}
//		ctx.close();
	}
}
```

## 実行結果
実行すると以下の出力が得られます。
とりあえず、TWE-Lite-USBは1秒間隔でカウンタを出力しているのが読み取れています。
よし！繋がってる！

```text:output
found COM5
found COM1
found COM3
Serial port responded with not-OK: ::ts=2743
Serial port responded with not-OK: ::ts=2744
Serial port responded with not-OK: ::ts=2745
Serial port responded with not-OK: ::ts=2746
Serial port responded with not-OK: ::ts=2747
Serial port responded with not-OK: ::ts=2748
```

# 評価

"[netty-transport-purejavacomm](https://github.com/steveturner/netty-transport-purejavacomm)"をコピペして使わないといけないのは、ちょっと気になるところですが、ネイティブライブラリを意識しなくてよいので気楽です。
お手軽に通信してみたいときにいかがでしょうか？