LoginSignup
0
2

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-06-17
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);
    }

}
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2