marunomaruno-memo

marunomaruno-memo

[leJOS][NXT] Bluetooth を使った送受信

2012年05月11日 | LEGO
[leJOS][NXT] Bluetooth を使った送受信
================================================================================

※ このサンプルは leJOS 0.9.1 で作成している。

Bluetooth を使って、データを送受信する。
プログラムは以下の 3 つを作った。

Sender11      リモートデバイス側。NXT のセンサーから値を読んで、Bluetooth を使っ
              て相手(Receiver11)に送信する

Receiver11    ローカルデバイス側。Sender11 から送られてきたデータを受信して、画
              面に表示する。

SensorValues  エンティティ。送受信時に使う NXT のセンサーの値を保持する。

Bluetooth では、データを送受信するときに、リモートデバイス側とローカルデバイス側
とで通信をする。このとき、リモートデバイス側のプログラム(Sender11)を先に起動して
おく。


■ リモートデバイス側

NXT の Esacape ボタン以外を押下したときに、各センサーの値を読み取って、相手の 
NXT に送信する。Esacape ボタンを押下したときは、プログラムを終了する。


□ Sender11.java
---
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import lejos.nxt.Button;
import lejos.nxt.LCD;
import lejos.nxt.LightSensor;
import lejos.nxt.Motor;
import lejos.nxt.SensorPort;
import lejos.nxt.SoundSensor;
import lejos.nxt.TouchSensor;
import lejos.nxt.UltrasonicSensor;
import lejos.nxt.comm.Bluetooth;
import lejos.nxt.comm.NXTConnection;

/**
 * NXTのセンサーからデータを取得し、Bluetoothを使って値を送信する。
 * リモートデバイス側(先にこちらのプログラムを起動しておく)
 * leJOS 0.9.1
 * @author marunomaruno
 * @version 1.0, 2012/03/14
 * @since 1.0
 */
public class Sender11 {
    public static void main(String[] args) throws Exception {
        // センサーを設定する
        TouchSensor touchSensor = new TouchSensor(SensorPort.S1);
        SoundSensor soundSensor = new SoundSensor(SensorPort.S2);
        LightSensor lightSensor = new LightSensor(SensorPort.S3);
        UltrasonicSensor ultrasonicSensor = new UltrasonicSensor(SensorPort.S4);

        // センサーが安定するまで待つ
        Thread.sleep(200);

        // ローカルデバイスとの通信を待つ
        LCD.drawString("Waiting...", 0, 0);
        NXTConnection connection = Bluetooth.waitForConnection();    // (1)

        // 接続できない場合、プログラムを終了する
        if (connection == null) {    // (2)
            LCD.clear();
            LCD.drawString("Connect fail", 0, 0);
            Button.waitForAnyPress();
            System.exit(1);
        }

        // ローカルにもログをとっておく
        File file = new File("values.dat");
        file.delete();
        file.createNewFile();
        DataOutputStream log = new DataOutputStream(new FileOutputStream(
                file));

        // Bluetooth 用のデータストリームを取得する
        DataOutputStream out = connection.openDataOutputStream();    // (3)

        // センサー値を保持するオブジェクトを確保する
        SensorValues values = new SensorValues();    // (4)

        // ESCが押されたら終わり
        while (Button.waitForAnyPress() != Button.ID_ESCAPE) {
            try {
                // IDをカウントアップする
                values.id++;

                // センサーから値を取得する
                values.buttonId = Button.readButtons();
                values.touch = touchSensor.isPressed() ? 1 : 0;
                values.sound = soundSensor.readValue();
                values.light = lightSensor.readValue();
                values.ultrasonic = ultrasonicSensor.getDistance();

                values.tachoCountA = Motor.A.getTachoCount();
                values.tachoCountB = Motor.B.getTachoCount();
                values.tachoCountC = Motor.C.getTachoCount();

                // データを画面に表示する
                LCD.clear();
                values.print(System.out);

                // ログファイルに出力する
                values.write(log);

                // Bluetoothに出力する
                values.write(out);    // (5)

            } catch (IOException e) {
                System.out.println(" write error " + e);
            }
        }

        // ログファイルを閉じる
        try {
            log.close();

        } catch (IOException e) {
            LCD.drawString("Close Exception", 0, 0);
            LCD.drawString(e.getMessage(), 0, 1);
            Button.waitForAnyPress();
        }

        // 通信を閉じる
        try {
            LCD.clear();
            LCD.drawString("Closing... ", 0, 0);
            out.close();    // (6)
            connection.close();    // (7)

        } catch (IOException e) {
            LCD.drawString("Close Exception", 0, 0);
            LCD.drawString(e.getMessage(), 0, 1);
            Button.waitForAnyPress();
        }

        // 終了メッセージを表示する
        LCD.clear();
        LCD.drawString("Finished", 0, 0);
        Button.waitForAnyPress();
    }
}
----

(1) ローカルデバイスとの通信を待つ

Bluetooth クラス の waitForConnection() メソッドを使って、ローカルデバイスとの通
信を待つ。通信があれば、待ち状態は解除され、BTConnection オブジェクトが返る。
なお、NXTConnection は、BTConnection のスーパークラス。

    NXTConnection connection = Bluetooth.waitForConnection();    // (1)

---
static BTConnection waitForConnection() 
          現在のデフォルトの PIN を使って取得する。
---

PIN は、ペアリングするときに使用する 4 桁の数字。デフォルトだと、「0000」または
「1234」。


□ Bluetooth クラス

java.lang.Object
  lejos.nxt.comm.NXTCommDevice
      lejos.nxt.comm.Bluetooth

Bluetooth 通信をあらわすクラス。

メソッド
---
static BTConnection connect(RemoteDevice remoteDevice) 
static BTConnection connect(String target, int mode) 
static BTConnection connect(String target, int mode, byte[] pin) 

static RemoteDevice getKnownDevice(String fName) 
static ArrayList<RemoteDevice> getKnownDevicesList() 

static BTConnection waitForConnection() 
static BTConnection waitForConnection(int timeout, int mode) 
static BTConnection waitForConnection(int timeout, int mode, byte[] pin) 
---


□ BTConnection クラス

java.lang.Object
  extended by lejos.nxt.comm.NXTConnection
      extended by lejos.nxt.comm.BTConnection

Bluetooth の接続をあらわすクラス。つぎに示す NXTConnection クラスを継承している。

メソッド
---
void  closeStream()
int   getSignalStrength()
void  openStream()
void  setActiveMode(int mode)
---


□ NXTConnection クラス

java.lang.Object
  lejos.nxt.comm.NXTConnection

一般的な NXT leJOS の接続を表すクラス。


メソッド
---
void             close() 
DataInputStream  openDataInputStream() 
DataOutputStream openDataOutputStream() 
InputStream      openInputStream() 
OutputStream     openOutputStream() 
---


(2) 接続できない場合、プログラムを終了する

Bluetooth.waitForConnection() メソッドで、接続ができない場合は、null が返るので、
これをチェックする。

    if (connection == null) {    // (2)


(3) Bluetooth 用のデータストリームを取得する

このプログラムは、センサーから読み取ったデータを相手に送信する側なので、出力スト
リームを開く。

    DataOutputStream out = connection.openDataOutputStream();    // (3)


(4) センサー値を保持するオブジェクトを確保する

NXT のセンサーからの値は、SensorValues オブジェクトとして生成する。

    SensorValues values = new SensorValues();    // (4)


(5) Bluetooth に出力する

SensorValues オブジェクトの write() メソッドに、Bluetooth の出力ストリーム・オブ
ジェクトを渡して書き込む。

    values.write(out);    // (5)


(6)(7) 通信を閉じる

通信が終わったら、出力ストリーム、接続ともに閉じる。

    out.close();    // (6)
    connection.close();    // (7)


■ ローカルデバイス側

Bluetooth を使って送られてきたデータを受信して、その値を表示するプログラム。
リモートデバイス側の名前を指定して、相手を特定する。


□ Receiver11.java
---
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.bluetooth.RemoteDevice;

import lejos.nxt.Button;
import lejos.nxt.LCD;
import lejos.nxt.comm.Bluetooth;
import lejos.nxt.comm.NXTConnection;

/**
 * Bluetoothを使って送られてきたデータを受信して、その値を表示する。
 * ローカルデバイス側(先に、リモートデバイス側を起動しておく)
 * leJOS 0.9.1
 * @author marunomaruno
 * @version 1.0, 2011/08/14
 * @since 1.0
 */
public class Receiver11 {
    public static void main(String[] args) throws Exception {

        // リモートデバイスと接続する
        LCD.drawString("Connecting...", 0, 0);

        // リモートデバイスのNXT名を設定する
        RemoteDevice device = Bluetooth.getKnownDevice("NXT名");    // (1)

        // リモートデバイスが見つからない場合、プログラムを終了する
        if (device == null) {
            LCD.clear();
            LCD.drawString("No such device", 0, 0);
            Button.waitForAnyPress();
            System.exit(1);
        }

        // 接続する
        NXTConnection connection = Bluetooth.connect(device);    // (2)

        // 接続できない場合、プログラムを終了する
        if (connection == null) {
            LCD.clear();
            LCD.drawString("Connect fail", 0, 0);
            Button.waitForAnyPress();
            System.exit(1);
        }

        // データストリームを開く
        DataInputStream in = connection.openDataInputStream();    // (3)

        // ローカルにもログをとっておく
        File file = new File("values.dat");
        file.delete();
        file.createNewFile();
        DataOutputStream log = new DataOutputStream(new FileOutputStream(file));

        SensorValues values = new SensorValues();

        // メッセージを受け取る
        try {
            while (Button.ESCAPE.isDown() != true) {
                // ストリームから値を読み込む
                values.read(in);    // (4)

                // ログファイルに出力する
                values.write(log);

                // データを画面に表示する
                LCD.clear();
                values.print(System.out);

                // 待つ
                Thread.sleep(200);
            }

        } catch (IOException e) {
            System.out.println(" write error " + e);
        }

        // ログファイルを閉じる
        try {
            log.close();

        } catch (IOException e) {
            LCD.drawString("Close Exception", 0, 0);
            LCD.drawString(e.getMessage(), 0, 1);
            Button.waitForAnyPress();
        }

        // 通信を閉じる
        try {
            LCD.clear();
            LCD.drawString("Closing...", 0, 0);
            in.close();
            connection.close();

        } catch (IOException e) {
            LCD.drawString("Close Exception", 0, 0);
            LCD.drawString(e.getMessage(), 0, 1);
            Button.waitForAnyPress();
        }

        LCD.clear();
        LCD.drawString("Finished", 0, 0);
        Button.waitForAnyPress();
    }

}
---

(1) リモートデバイスのNXT名を設定する

Bluetooth クラスの getKnownDevice() メソッドを使って、相手のデバイス名を指定して、
接続先のデバイスを取得する。

    RemoteDevice device = Bluetooth.getKnownDevice("NXT名");    // (1)

リモートデバイスが見つからない場合は、null が返る。


Bluetooth クラスのメソッド
---
static RemoteDevice getKnownDevice(String fName) 
static ArrayList<RemoteDevice> getKnownDevicesList() 
---


□ RemoteDevice クラス

java.lang.Object
  javax.bluetooth.RemoteDevice

リモートデバイスをあらわすクラス。


主なメソッド
---
 String  getBluetoothAddress() 
 String  getDeviceAddr() 
 int     getDeviceClass() 
 String  getFriendlyName(boolean alwaysAsk) 
static RemoteDevice getRemoteDevice(Connection conn) 
 boolean isAuthenticated() 
 boolean isEncrypted() 
 void    setDeviceAddr(String deviceAddr) 
 void    setFriendlyName(String fName) 
---


(2) 接続する

    NXTConnection connection = Bluetooth.connect(device);    // (2)

接続できない場合は、null が返る。


Bluetooth クラスのメソッド
---
static BTConnection connect(RemoteDevice remoteDevice) 
static BTConnection connect(String target, int mode) 
static BTConnection connect(String target, int mode, byte[] pin) 
---


(3) データストリームを開く

このプログラムは、Bluetooth から受信した値を画面に表示するので、入力ストリームを
開く。

    DataInputStream in = connection.openDataInputStream();    // (3)


(4) ストリームから値を読み込む

SensorValues オブジェクトの read() メソッドに、Bluetooth の入力ストリーム・オブ
ジェクトを渡して書き込む。

    values.read(in);    // (4)


■ エンティティ

NXT のセンサーの値を管理するエンティティ・クラス。
入力ストリームや出力ストリームのオブジェクトを受け取ることで、そのストリームに対
する入出力も行う。
なお、データの値は int 値として送受信している。

管理している値はつぎのとおり。
    ------------- ------------------------
    フィールド名  意味
    ------------- ------------------------
    id            ID
    buttonId      ボタンのID
    touch         タッチセンサーの値
    sound         音センサーの値
    light         光センサーの値
    ultrasonic    超音波センサーの値
    tachoCountA   モーターAのタコカウント
    tachoCountB   モーターBのタコカウント
    tachoCountC   モーターCのタコカウント
    ------------- ------------------------


□ SensorValues.java
---
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.PrintStream;

/**
 * NXTのセンサーの値を保持するエンティティ
 * leJOS 0.9.1, Android 2.2
 * @author marunomaruno
 * @version 1.0, 2012/03/14
 * @since 1.0
 */
public class SensorValues {

    int id;    // ID

    int buttonId;    // ボタンのID
    int touch;    // タッチセンサーの値
    int sound;    // 音センサーの値
    int light;    // 光センサーの値
    int ultrasonic;    // 超音波センサーの値

    int tachoCountA;    // モーターAのタコカウント
    int tachoCountB;    // モーターBのタコカウント
    int tachoCountC;    // モーターCのタコカウント

    /**
     * 値を表示する。
     * @param out 表示するストリーム
     */
    public void print(PrintStream out) {
        out.println(id);
        out.println(toSensorString());
        out.println(toMotorString());
    }

    /**
     * データを入力する。
     * @param in 入力ストリーム
     * @throws IOException
     */
    public void read(DataInputStream in) throws IOException {
        id = in.readInt();

        buttonId = in.readInt();
        touch = in.readInt();
        sound = in.readInt();
        light = in.readInt();
        ultrasonic = in.readInt();

        tachoCountA = in.readInt();
        tachoCountB = in.readInt();
        tachoCountC = in.readInt();
    }

    /**
     * データを出力する。
     * @param out 出力ストリーム
     * @throws IOException
     */
    public void write(DataOutputStream out) throws IOException {
        out.writeInt(id);

        out.writeInt(buttonId);
        out.writeInt(touch);
        out.writeInt(sound);
        out.writeInt(light);
        out.writeInt(ultrasonic);

        out.writeInt(tachoCountA);
        out.writeInt(tachoCountB);
        out.writeInt(tachoCountC);

        out.flush();
    }

    /**
     * すべてのセンサーの値からなる文字列を組み立てる。
     * @return 組み立てた文字列
     */
    public String toSensorString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        sb.append(buttonId);
        sb.append(", ");
        sb.append(touch);
        sb.append(", ");
        sb.append(sound);
        sb.append(", ");
        sb.append(light);
        sb.append(", ");
        sb.append(ultrasonic);
        sb.append("]");

        return sb.toString();
    }

    /**
     * すべてのモーターの値からなる文字列を組み立てる。
     * @return 組み立てた文字列
     */
    public String toMotorString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        sb.append(toMotorString(new int[]{tachoCountA}));
        sb.append(", ");
        sb.append(toMotorString(new int[]{tachoCountB}));
        sb.append(", ");
        sb.append(toMotorString(new int[]{tachoCountC}));
        sb.append("]");

        return sb.toString();
    }

    /**
     * 指定されたモーター値の配列からなる文字列を組み立てる。
     * @param values 値の配列
     * @return 組み立てた文字列
     */
    public String toMotorString(int[] values) {
        if (values.length == 0) {
            return "[]";
        }

        StringBuilder sb = new StringBuilder();
        sb.append("[");
        sb.append(values[0]);
        for (int i = 1; i < values.length; i++) {
            sb.append(", ");
            sb.append(values[i]);
        }
        sb.append("]");

        return sb.toString();
    }

    /*
     * (非 Javadoc)
     *
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(id);

        sb.append("[");
        sb.append(toSensorString());
        sb.append(", ");
        sb.append(toMotorString());
        sb.append("]");

        return sb.toString();
    }
}
---

                                                                            以上


最新の画像もっと見る

コメントを投稿