package com.nutiteq.bluetooth;
import java.io.IOException;
import java.util.Vector;
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.bluetooth.UUID;
import javax.microedition.io.Connector;
import com.nutiteq.location.providers.LocationDataConnection;
import com.nutiteq.location.providers.LocationDataConnectionProvider;
import com.nutiteq.log.Log;
/**
* Bluetooth devices implemented on top of Bluetooth API (JSR-82)
*/
public class BluetoothAPIDevice implements BluetoothDevice, DiscoveryListener,
LocationDataConnectionProvider {
public static final int BLUETOOTH_TIMEOUT = 30000;
private final Vector btDevicesFound = new Vector();
public Vector btServicesFound = new Vector();
private boolean isBTSearchComplete;
private final BluetoothHandler handler;
/**
* Create new browser with caller, that could handle found devices.
*
* @param handler
* handler for receiving found devices
*/
public BluetoothAPIDevice(final BluetoothHandler handler) {
this.handler = handler;
}
/**
* Find all remote devices supporting serial port connection and report them
* to {@link BluetoothHandler}.
*/
public void findRemoteDevices() {
findDevices();
findServices(new UUID[] { new UUID(UUID_SERIALPORT) });
}
private void findDevices() {
try {
// cleans previous elements
btDevicesFound.removeAllElements();
isBTSearchComplete = false;
final LocalDevice local = LocalDevice.getLocalDevice();
final DiscoveryAgent discoveryAgent = local.getDiscoveryAgent();
// discover new devices
discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this);
while (!isBTSearchComplete) {
// waits for a fixed time, to avoid long search
synchronized (this) {
this.wait(BLUETOOTH_TIMEOUT);
}
// check if search is completed
if (!isBTSearchComplete) {
// search no yet completed so let's cancel it
discoveryAgent.cancelInquiry(this);
}
}
} catch (final Exception e) {
Log.error("BT: find " + e.getMessage());
Log.printStackTrace(e);
}
}
private void findServices(final UUID[] aServices) {
btServicesFound.removeAllElements();
try {
final LocalDevice local = LocalDevice.getLocalDevice();
final DiscoveryAgent discoveryAgent = local.getDiscoveryAgent();
// discover services
if (btDevicesFound.size() > 0) {
for (int i = 0; i < btDevicesFound.size(); i++) {
isBTSearchComplete = false;
// adds a null element in case we don't find service
btServicesFound.addElement(null);
final int transID = discoveryAgent.searchServices(null, aServices,
(RemoteDevice) (btDevicesFound.elementAt(i)), this);
// wait for service discovery ends
synchronized (this) {
this.wait(BLUETOOTH_TIMEOUT);
}
if (!isBTSearchComplete) {
discoveryAgent.cancelServiceSearch(transID);
}
}
}
final DiscoveredDevice[] devices = new DiscoveredDevice[btDevicesFound.size()];
for (int i = 0; i < devices.length; i++) {
String name = null;
String url = null;
try {
name = ((RemoteDevice) btDevicesFound.elementAt(i)).getFriendlyName(false);
final ServiceRecord elementAt = (ServiceRecord) btServicesFound.elementAt(i);
if (elementAt != null) {
url = elementAt.getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);
}
} catch (final IOException e) {
Log.printStackTrace(e);
}
devices[i] = new DiscoveredDevice(name, url);
}
handler.remoteDevicesFound(devices);
} catch (final Exception e) {
Log.printStackTrace(e);
Log.error("findServices: " + e.getMessage());
}
}
public void deviceDiscovered(final RemoteDevice remoteDevice, final DeviceClass dClass) {
try {
Log.debug(remoteDevice.getFriendlyName(false));
} catch (final IOException e) {
}
btDevicesFound.addElement(remoteDevice);
}
public void inquiryCompleted(final int discType) {
isBTSearchComplete = true;
// notifies and wake main thread that device search is completed
synchronized (this) {
this.notify();
}
}
public void serviceSearchCompleted(final int transId, final int respCode) {
isBTSearchComplete = true;
// notifies and wake mains thread that service search is completed
synchronized (this) {
this.notify();
}
}
public void servicesDiscovered(final int param, final ServiceRecord[] serviceRecord) {
final int index = btServicesFound.size() - 1;
for (int i = 0; i < serviceRecord.length; i++) {
btServicesFound.setElementAt(serviceRecord[i], index);
}
}
public LocationDataConnection openConnection(final String url) throws IOException {
return new BluetoothAPIConnection(Connector.open(url));
}
}