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通信 のサーバー側クラスをもとに作成。
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);
}
}