Aspire :: OSGi Bundles :: Bluetooth Server



Goal

This bundle provides a multi-client bluetooth server. It provides a BluetoothServerService service when activated, and must be configured before being the server really starts.

It uses the Bluecove JSR82 implementation, so all the device configuration may be done by setting Java system properties (see the bluecove documentation).

The server waits for a new client via a blocking call, so run it in a specific thread. Each client is run in a thread, due to blocking InputStream calls.

Sample usage

How to start the server

// Read properties and threads
BluetoothServerService m_server = new BluetoothServerImpl();

// Set the device discoverable m_server.prepareServer();

// Start listening in a special thread m_server.startServer();

How to stop the server

m_server.stop();

How to configure the server

The server can be configured via a property XML file, given as an InputStream parameter to the prepareServer() method.

Sample : Read a configuration XML file embedded in the bundle JAR file.

m_server.prepareServer(getClass().getResourceAsStream("/bluetoothConfig.xml"));

Parameters :

KeyTypeDescriptionDefault
uuidStringServer's "Universally" Unique IDentifier 
serviceNameStringServer's name 
authenticatebooleanServer needs client authentificationfalse
encryptbooleanCommunication must be encryptedfalse
inquiryModeintType of inquiries to respond to (GIAC or LIAC) (see http://bluecove.org/bluecove/apidocs/javax/bluetooth/DiscoveryAgent.html)GIAC
debugbooleanVerbose modefalse
readingModeBYTE, CHAR or UTFWhich DataInputStream reading method must be used (readByte, readChar or readUTF)CHAR
max_threadsintMaximum number of communication threads (not used) 

How to read data from devices

This bundle use a listener model : each class who needs to read communication data must implement the CommunicationListener interface.

This interface provides three functions :

  • commBegin(String logicalName) : Called when a client has just connected the server, logicalName is UUID generated by the server to identify a connection
  • commEnd(String logicalName) : Called when a client has ended the connection, or when the server stops.
  • commRead(String logicalName, String data) : Called when the server read a line from the client.
The logical name is the client unique identifier, based on its Bluetooth address and its friendly name (if present).

class BluetoothComm implements CommunicationListener {
  private BluetoothServerService m_server;

public BluetoothComm() m_server = new BluetoothServerImpl(); m_server.prepareServer(getClass().getResourceAsStream("/bluetoothConfig.xml")); m_server.startServer(); m_server.addCommunicationListener(this); }

public void commBegin(String logicalName) { System.out.println("Client connected : " + logicalName); }

public void commEnd(String logicalName) { System.out.println("Client gone : " + logicalName); }

public void commRead(String logicalName, String data) { System.out.println("Read '" + data + "' from " + logicalName);

// Write some data in response try { m_server.getCommunication(logicalName).writeData("ACKn"); } catch (IOException e) { // Error occurred during write process } } }

Issues under Linux

License issue

  • For latest versions BlueZ (v4 and higher), this bundle needs bluecove-gpl library to work, under GPL.
  • For older versions, it may be possible to use bluecove-bluez instead, under Apache License 2.0 (not tested).

Rights issue

This bundle needs to have root rights in order to set the device discoverable.

A solution to bypass this problem is to set the device discoverable in system wide configuration. (It can be done with user rights with gnome-bluetooth, for example).

Test

Operating systems

  • Windows
    • Windows 7, 32 bits version
  • Linux
    • Fedora 13, 64 bits version, with bluecove-gpl

Dongles

  • Built-in AsusTEK bluetooth device, with generic drivers

Hints for future improvements

  • Control the number of client threads, by aggregating them in a thread pool.