[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();
}
}
---
以上