マイクロビットからラズパイ経由でMIDI音源を鳴らすことを目標にしています。イメージ図は下のようなものです。
今回はここのMicrobitからラズパイ(RPi)へデータを飛ばした時にラズパイで受け取るための装置を作ろうと思っています。
Bluetooth通信
ラズパイ上でBluetooth通信をしたいと思い、色々と調べているとこのようなページを見つけました。
ここにはBlueCoveというライブラリを使用してラズパイでJavaを起動してBluetooth通信を行う時につまづいたのでなにやらとやり取りをしている掲示板でした。
早い話が、BlueCoveをつかえばBluetoothを使用できそうだということです。がしかしプロジェクトは終了しているのか、メインプロジェクト
上のような規格(仕様)があります、大雑把に、Bluetooth通信の仕様を決めているものです。上のリンク先がJSR-82のサイトになります。JSR 82: JavaTM APIs for Bluetooth
そして、JavaTM APIs for Bluetoothのページからダウンロードできるようです。しかし、色々あってよくわからな買ったので最後に行き着いたとこのリンクをここに貼っておきます。
zipファイルにjavax.bluetooth.*が入っていました。そして下にあるサンプルコードが記載されているPDFファイルも入っているのでそれも参照します。
このZIPファイルをダウンロードして、Eclipseの設定からビルドパスに追加します。
そうすると下のように「javax.bluetooth.*」をインポートでいます。
ここからがBluetoothとの戦いが始まります。そして、これはクライアントアプリのサンプルコードです。
目的の実装はサーバー側の実装になりますが、入り口(イントロダクション)的に下に記載します。
Bluetoothサンプルコード
ちょうどダウンロードしたZIPに(上のZIPファイルに)PDFファイルが入っていましたので、ここに記載します。(コピペです)
こいつ(サンプルコード)を参考にBluetooth通信を試みます。
<とりあえずはクライアント側の実装です。>
import java.lang.*;
import java.io.*;
import java.util.*;
import javax.microedition.io.*;
import javax.bluetooth.*;
/**
* This class shows a simple client application that performs device
* and service
* discovery and communicates with a print server to show how the Java * API for Bluetooth wireless technology works.
*/
public class PrintClient implements DiscoveryListener {
/**
* The DiscoveryAgent for the local Bluetooth device. */
private DiscoveryAgent agent;
/**
* The max number of service searches that can occur at any one time. */
private int maxServiceSearches = 0;
/**
* The number of service searches that are presently in progress. */
private int serviceSearchCount;
/**
* Keeps track of the transaction IDs returned from searchServices. */
private int transactionID[];
/**
* The service record to a printer service that can print the message
April 5, 2002 Java APIs for Bluetooth Wireless Technology (JSR-82)
21
ALL RIGHTS RESERVED UNDER JSPA (JAVA SPECIFICATION PARTICIPATION AGREEMENT)
* provided at the command line.
*/
private ServiceRecord record;
/**
* Keeps track of the devices found during an inquiry. */
private Vector deviceList;
/**
* Creates a PrintClient object and prepares the object for device
* discovery and service searching.
*
* @exception BluetoothStateException if the Bluetooth system could not be * initialized
*/
public PrintClient() throws BluetoothStateException {
/*
* Retrieve the local Bluetooth device object. */
LocalDevice local = LocalDevice.getLocalDevice();
/*
* Retrieve the DiscoveryAgent object that allows us to perform device * and service discovery.
*/
agent = local.getDiscoveryAgent();
/*
* Retrieve the max number of concurrent service searches that can * exist at any one time.
*/
try {
maxServiceSearches = Integer.parseInt(
LocalDevice.getProperty("bluetooth.sd.trans.max")); } catch (NumberFormatException e) {
System.out.println("General Application Error");
System.out.println("\tNumberFormatException: " + e.getMessage()); }
transactionID = new int[maxServiceSearches];
// Initialize the transaction list
for (int i = 0; i < maxServiceSearches; i++) {
transactionID[i] = -1;
}
record = null;
deviceList = new Vector();
}
/**
* Adds the transaction table with the transaction ID provided. *
* @param trans the transaction ID to add to the table */
private void addToTransactionTable(int trans) {
for (int i = 0; i < transactionID.length; i++) {
if (transactionID[i] == -1) {
transactionID[i] = trans;
return;
} }
}
/**
* Removes the transaction from the transaction ID table. *
* @param trans the transaction ID to delete from the table */
private void removeFromTransactionTable(int trans) { for (int i = 0; i < transactionID.length; i++) {
if (transactionID[i] == trans) {
transactionID[i] = -1;
return;
} }
}
/**
* Completes a service search on each remote device in the list until all
* devices are searched or until a printer is found that this application * can print to.
*
* @param devList the list of remote Bluetooth devices to search *
* @return true if a printer service is found; otherwise false if
* no printer service was found on the devList provided */
private boolean searchServices(RemoteDevice[] devList) { UUID[] searchList = new UUID[2];
/*
* Add the UUID for L2CAP to make sure that the service record
* found will support L2CAP. This value is defined in the * Bluetooth Assigned Numbers document.
*/
searchList[0] = new UUID(0x0100);
/*
* Add the UUID for the printer service that we are going to use to
* the list of UUIDs to search for. (a fictional printer service UUID) */
searchList[1] = new UUID("1020304050d0708093a1b121d1e1f100", false);
/*
* Start a search on as many devices as the system can support. */
for (int i = 0; i < devList.length; i++) {
/*
* If we found a service record for the printer service, then * we can end the search.
*/
if (record != null) {
return true;
}
try {
int trans = agent.searchServices(null, searchList, devList[i],
this);
addToTransactionTable(trans);
} catch (BluetoothStateException e) {
/*
* Failed to start the search on this device, try another * device.
*/
}
/*
* Determine if another search can be started. If not, wait for * a service search to end.
*/
synchronized (this) {
ALL RIGHTS RESERVED UNDER JSPA (JAVA SPECIFICATION PARTICIPATION AGREEMENT)
} }
serviceSearchCount++;
if (serviceSearchCount == maxServiceSearches) {
try {
this.wait();
} catch (Exception e) {
} }
/*
* Wait until all the service searches have completed. */
while (serviceSearchCount > 0) {
synchronized (this) {
try {
this.wait();
} catch (Exception e) {
} }
}
if (record != null) {
return true;
} else {
return false;
} }
/**
* Finds the first printer that is available to print to.
*
* @return the service record of the printer that was found; null if no * printer service was found
*/
public ServiceRecord findPrinter() {
/*
* If there are any devices that have been found by a recent inquiry,
* we don't need to spend the time to complete an inquiry. */
RemoteDevice[] devList = agent.retrieveDevices(DiscoveryAgent.CACHED); if (devList != null) {
if (searchServices(devList)) {
return record;
} }
/*
* Did not find any printer services from the list of cached devices.
* Will try to find a printer service in the list of pre-known * devices.
*/
devList = agent.retrieveDevices(DiscoveryAgent.PREKNOWN); if (devList != null) {
if (searchServices(devList)) {
return record;
} }
/*
* Did not find a printer service in the list of pre-known or cached
* devices. So start an inquiry to find all devices that could be a * printer and do a search on those devices.
*/
/* Start an inquiry to find a printer */
try {
agent.startInquiry(DiscoveryAgent.GIAC, this);
/*
* Wait until all the devices are found before trying to start the * service search.
*/
synchronized (this) {
try {
this.wait();
} catch (Exception e) {
} }
} catch (BluetoothStateException e) { System.out.println("Unable to find devices to search");
}
if (deviceList.size() > 0) {
devList = new RemoteDevice[deviceList.size()]; deviceList.copyInto(devList);
if (searchServices(devList)) {
return record;
ALL RIGHTS RESERVED UNDER JSPA (JAVA SPECIFICATION PARTICIPATION AGREEMENT)
} }
return null;
}
/**
* This is the main method of this application. It will print out * the message provided to the first printer that it finds.
*
* @param args[0] the message to send to the printer
*/
public static void main(String[] args) {
PrintClient client = null;
/*
* Validate the proper number of arguments exist when starting this * application.
*/
if ((args == null) || (args.length != 1)) { System.out.println("usage: java PrintClient message"); return;
}
/*
* Create a new PrintClient object.
*/
try {
client = new PrintClient();
} catch (BluetoothStateException e) { System.out.println("Failed to start Bluetooth System"); System.out.println("\tBluetoothStateException: " +
}
/*
* Find a printer in the local area
*/
ServiceRecord printerService = client.findPrinter(); if (printerService != null) {
/*
* Determine if this service will communicate over RFCOMM or * L2CAP by retrieving the connection string.
e.getMessage());
ALL RIGHTS RESERVED UNDER JSPA (JAVA SPECIFICATION PARTICIPATION AGREEMENT)
*/
String conURL = printerService.getConnectionURL(
ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false); int index= conURL.indexOf(':');
String protocol= conURL.substring(0, index);
if (protocol.equals("btspp")) {
/*
* Since this printer service uses RFCOMM, create an RFCOMM * connection and send the data over RFCOMM.
*/
/* code to call RFCOMM client goes here */
} else if (protocol.equals("btl2cap")) {
/*
* Since this service uses L2CAP, create an L2CAP
* connection to the service and send the data to the
* service over L2CAP.
*/
/* code to call L2CAP client goes here */
} else {
System.out.println("Unsupported Protocol");
}
} else {
System.out.println("No Printer was found");
} }
/**
* Called when a device was found during an inquiry. An inquiry
* searches for devices that are discoverable. The same device may * be returned multiple times.
*
* @see DiscoveryAgent#startInquiry
*
* @param btDevice the device that was found during the inquiry *
* @param cod the service classes, major device class, and minor
* device class of the remote device being returned *
April 5, 2002 Java APIs for Bluetooth Wireless Technology (JSR-82)
28
ALL RIGHTS RESERVED UNDER JSPA (JAVA SPECIFICATION PARTICIPATION AGREEMENT)
*/
public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod) {
/*
* Since service search takes time and we are already forced to * complete an inquiry, we will not do a service
* search on any device that is not an Imaging device.
* The device class of 0x600 is Imaging as
* defined in the Bluetooth Assigned Numbers document.
*/
if (cod.getMajorDeviceClass() == 0x600) { /*
} }
* Imaging devices could be a display, camera, scanner, or * printer. If the imaging device is a printer,
* then bit 7 should be set from its minor device
* class according to the Bluetooth Assigned
* Numbers document.
*/
if ((cod.getMinorDeviceClass() & 0x80) != 0) {
/*
* Now we know that it is a printer. Now we will verify that
* it has a rendering service on it. A rendering service may
* allow us to print. We will have to do a service search to
* get more information if a rendering service exists. If this
* device has a rendering service then bit 18 will be set in * the major service classes.
*/
if ((cod.getServiceClasses() & 0x40000) != 0) { deviceList.addElement(btDevice);
} }
/**
* The following method is called when a service search is completed or
* was terminated because of an error. Legal status values * include:
* SERVICE_SEARCH_COMPLETED
,
* SERVICE_SEARCH_TERMINATED
,
* SERVICE_SEARCH_ERROR
,
* SERVICE_SEARCH_DEVICE_NOT_REACHABLE
, and
* SERVICE_SEARCH_NO_RECORDS
. *
* @param transID the transaction ID identifying the request which
* initiated the service search
*
* @param respCode the response code which indicates the
* status of the transaction; guaranteed to be one of the * aforementioned only
*
*/
public void serviceSearchCompleted(int transID, int respCode) {
/*
* Removes the transaction ID from the transaction table. */
removeFromTransactionTable(transID);
serviceSearchCount--;
synchronized (this) {
this.notifyAll();
} }
/**
* Called when service(s) are found during a service search.
* This method provides the array of services that have been found. *
* @param transID the transaction ID of the service search that is * posting the result
*
* @param service a list of services found during the search request *
* @see DiscoveryAgent#searchServices
*/
public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
/*
* If this is the first record found, then store this record * and cancel the remaining searches.
*/
if (record == null) {
record = servRecord[0];
/*
* Cancel all the service searches that are presently * being performed.
*/
April 5, 2002
Java APIs for Bluetooth Wireless Technology (JSR-82)
30
ALL RIGHTS RESERVED UNDER JSPA (JAVA SPECIFICATION PARTICIPATION AGREEMENT)
} }
でわでわ。。。