leJOS ev3 のBluetoothでブロックしないで通信するようにする

```
BTConnetor.WaitForConnection(int timeout, int mode)
```
はタイムアウトしないし、

```
BTConnection.read(byte[] buffer, int length, boolean wait)
```

は、読み込まれるまで待機してしまう。
これらを解消するために、ラッパークラスを作ってみた。

```BtNbConnector.java
import java.io.IOException;

import lejos.remote.nxt.BTConnector;
import lejos.remote.nxt.NXTCommConnector;
import lejos.remote.nxt.NXTConnection;
import lejos.utility.Stopwatch;

public class BtNbConnector extends NXTCommConnector implements Runnable {
	BTConnector connector;
	
	private NXTConnection con = null;
	private boolean connected = false;
	
	private int mode;
	
	public BtNbConnector() {
		connector = new BTConnector();
	}

	@Override
	public NXTConnection waitForConnection(int timeout, int mode) {
		this.mode = mode;
		
		new Thread(this).start();
		Stopwatch sw = new Stopwatch();
		
		while (!connected && sw.elapsed() < timeout) {
		}
		
		if (!connected) {
			return null;
		}
		
		return new BtNbConnection(con);
	}

	public void run() {
		con = connector.waitForConnection(0, mode);
		connected = true;
	}

	@Override
	public NXTConnection connect(String target, int mode) {
		return new BtNbConnection(connector.connect(target, mode);
	}

	@Override
	public boolean cancel() {
		return connector.cancel();
	}

}

class BtNbConnection extends NXTConnection implements Runnable {
	private NXTConnection con = null;
	
	BtNbConnection(NXTConnection con) {
		this.con = con;
	}


	@Override
	public void close() throws IOException {
		con.close();
	}


	@Override
	public int read(byte[] buf, int length) {
		return con.read(buf, length);
	}


	@Override
	public int write(byte[] buf, int numBytes) {
		return con.write(buf, numBytes);
	}

	private boolean received = false;
	private int rtn = 0;
	
	private byte[] buffer;
	private int length;
	
	private Thread reading = null; 

	@Override
	public int read(byte[] buf, int length, boolean wait) {
		if (wait) {
			return con.read(buf, length);
		}
		
		received = false;
		this.buffer = buf;
		this.length = length;

		// 受信する
		if (reading == null) {
			System.out.println("Thread start");
			reading = new Thread(this);
			reading.start();
		}
		
		// データを受信するか、20ミリ秒待つ
		Stopwatch sw = new Stopwatch();
		while (!received && sw.elapsed() < 20) {	
		}
		
		return rtn;
	}

	public void run() {
		rtn = con.read(buffer, length);
		received = true;
	}
	
}
```


使用例は、[leJOSによるEV3同士のBluetooth通信](http://qiita.com/amapyon/items/e6ed3cf83dbaa3893726) のサーバー側クラスをもとに作成。

```BluetoothServer.java
import lejos.hardware.Button;
import lejos.hardware.Sound;
import lejos.remote.nxt.NXTCommConnector;
import lejos.remote.nxt.NXTConnection;
import lejos.utility.Delay;

public class BluetoothServer {

	public static void main(String[] args) {
		int recvMessageNo = 2;  //受信する番号
		int sendMessageNo = 3;	//送信する番号

		System.out.println("Connect waiting...");

		// BtConnectorのラッパークラスのインスタンスを作成する
		NXTCommConnector connector = new BtNbConnector();

		// 送信先からの接続を待つ、★10秒でタイムアウト
		NXTConnection connection = connector.waitForConnection(10 * 1000, NXTConnection.RAW);
		
		if (connection == null) {
			// 接続が失敗したらシステムを終了する
			System.out.println("Connect fail");
			Delay.msDelay(3 * 1000);
			System.exit(1);
		}

		System.out.println("Connected");

		//受信番号が正しければ音を鳴らす
		if(isReceived(connection, recvMessageNo)){
			Sound.systemSound(false, 2);
		} else {
			Sound.buzz();
		}
		
		// メッセージを送信する
		send(connection, sendMessageNo);

		//通信を切断する
		System.out.println("Closing...");
		try {
			if (null != connection) {
				connection.close();
			}
		} catch (Exception ioe) {
		}

		System.out.println("Finished");

		Button.waitForAnyPress();
	}
	
	static boolean isReceived(NXTConnection connection, int messageNo) {
		byte[] recvBuff = new byte[16];
		
		//メッセージを受信するか、ESCAPEボタンが押されるまで待つ
		while(recvBuff[0] == 0 && Button.ESCAPE.isUp()){
			// ★待機せずに受信する
			connection.read(recvBuff, recvBuff.length, false);
		}

		//メッセージが正しいかチェックする
		for (int i = 0; i < recvBuff.length; i++) {
			System.out.print(recvBuff[i]);
			if (recvBuff[i] != messageNo) {
				System.out.println();
				return false;
			}
		}
		System.out.println();
		return true;
	}
	
	static void send(NXTConnection connection, int messageNo) {
		byte[] sendBuff = new byte[16];
		for (int i = 0; i < sendBuff.length; i++) {
			sendBuff[i] = (byte)messageNo;
		}
		connection.write(sendBuff, sendBuff.length);
	}

}
```