Let leJOS ev3 communicate with Bluetooth without blocking

BTConnetor.WaitForConnection(int timeout, int mode)

Does not time out and

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

Will wait until it is loaded. To solve these problems, I created a wrapper class.

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;

		//Receive
		if (reading == null) {
			System.out.println("Thread start");
			reading = new Thread(this);
			reading.start();
		}
		
		//Receive data or wait 20ms
		Stopwatch sw = new Stopwatch();
		while (!received && sw.elapsed() < 20) {	
		}
		
		return rtn;
	}

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

The usage example is created based on the server side class of Bluetooth communication between EV3s by leJOS.

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;  //Number to receive
		int sendMessageNo = 3;	//Number to send

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

		//Create an instance of the BtConnector wrapper class
		NXTCommConnector connector = new BtNbConnector();

		//Wait for a connection from the destination, ★ Time out in 10 seconds
		NXTConnection connection = connector.waitForConnection(10 * 1000, NXTConnection.RAW);
		
		if (connection == null) {
			//Shut down the system if the connection fails
			System.out.println("Connect fail");
			Delay.msDelay(3 * 1000);
			System.exit(1);
		}

		System.out.println("Connected");

		//Sounds if the reception number is correct
		if(isReceived(connection, recvMessageNo)){
			Sound.systemSound(false, 2);
		} else {
			Sound.buzz();
		}
		
		//Send a message
		send(connection, sendMessageNo);

		//Disconnect communication
		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];
		
		//Wait until you receive a message or press the ESCAPE button
		while(recvBuff[0] == 0 && Button.ESCAPE.isUp()){
			//★ Receive without waiting
			connection.read(recvBuff, recvBuff.length, false);
		}

		//Check if the message is correct
		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);
	}

}

Recommended Posts

Let leJOS ev3 communicate with Bluetooth without blocking
[LeJOS] Let's control the EV3 motor with Java
[LeJOS] Get EV3 sensor value remotely with Java
[LeJOS] Let's remotely control the EV3 motor with Java