<?xml version="1.0" encoding="UTF-8"?>

<xwikidoc>
<web>Main.Documentation.Bundles</web>
<name>BluetoothServer</name>
<language></language>
<defaultLanguage>en</defaultLanguage>
<translation>0</translation>
<parent>Main.Documentation.Bundles</parent>
<creator>xwiki:XWiki.donsez</creator>
<author>xwiki:XWiki.calmant</author>
<contentAuthor>xwiki:XWiki.calmant</contentAuthor>
<creationDate>1276181341000</creationDate>
<date>1282852311000</date>
<contentUpdateDate>1282852311000</contentUpdateDate>
<version>1.10</version>
<title>Aspire :: OSGi Bundles :: Bluetooth Server</title>
<template></template>
<content>1 Aspire :: OSGi Bundles :: Bluetooth Server

----
#toc("" "" "true")
----

1.1 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&gt;http://bluecove.org], so all the device configuration may be done by setting Java system properties (see [the bluecove documentation&gt;http://code.google.com/p/bluecove/wiki/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.

1.1 Sample usage

1.1.1 How to start the server

{code}
// 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();
{code}

1.1.1 How to stop the server

{code}
m_server.stop();
{code}

1.1.1 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.

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

Parameters :

{table}
Key|Type|Description|Default
uuid|String|Server's "Universally" Unique IDentifier|
serviceName|String|Server's name|
authenticate|boolean|Server needs client authentification|false
encrypt|boolean|Communication must be encrypted|false
inquiryMode|int|Type of inquiries to respond to (GIAC or LIAC) (see http://bluecove.org/bluecove/apidocs/javax/bluetooth/DiscoveryAgent.html)|GIAC
debug|boolean|Verbose mode|false
readingMode|BYTE, CHAR or UTF|Which DataInputStream reading method must be used (readByte, readChar or readUTF)|CHAR
max_threads|int|Maximum number of communication threads (not used)|
{table}

1.1.1 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).

{code}
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("ACK\n");
    }
    catch (IOException e) {
      // Error occurred during write process
    }
  }
}
{code}

1.1 Issues under Linux

1.1.1 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*).

1.1.1 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).

1.1 Test
1.1.1 Operating systems

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

1.1.1 Dongles

* Built-in AsusTEK bluetooth device, with generic drivers

1.1 Hints for future improvements

* Control the number of client threads, by aggregating them in a thread pool.</content>
<renderedcontent>&lt;h2 class="heading-1"&gt;&lt;span id="HAspire3A3AOSGiBundles3A3ABluetoothServer"&gt;Aspire :: OSGi Bundles :: Bluetooth Server&lt;/span&gt;&lt;/h2&gt;&lt;p class="paragraph"/&gt;&lt;hr class="line"/&gt;
            &lt;ul&gt;
          &lt;li&gt;&lt;a href="#HGoal"&gt;1 Goal&lt;/a&gt; 
      &lt;li&gt;&lt;a href="#HSampleusage"&gt;2 Sample usage&lt;/a&gt; 
        &lt;ul&gt;
          &lt;li&gt;&lt;a href="#HHowtostarttheserver"&gt;2.1 How to start the server&lt;/a&gt; 
      &lt;li&gt;&lt;a href="#HHowtostoptheserver"&gt;2.2 How to stop the server&lt;/a&gt; 
      &lt;li&gt;&lt;a href="#HHowtoconfiguretheserver"&gt;2.3 How to configure the server&lt;/a&gt; 
      &lt;li&gt;&lt;a href="#HHowtoreaddatafromdevices"&gt;2.4 How to read data from devices&lt;/a&gt; 
        &lt;/ul&gt;
          &lt;li&gt;&lt;a href="#HIssuesunderLinux"&gt;3 Issues under Linux&lt;/a&gt; 
        &lt;ul&gt;
          &lt;li&gt;&lt;a href="#HLicenseissue"&gt;3.1 License issue&lt;/a&gt; 
      &lt;li&gt;&lt;a href="#HRightsissue"&gt;3.2 Rights issue&lt;/a&gt; 
        &lt;/ul&gt;
          &lt;li&gt;&lt;a href="#HTest"&gt;4 Test&lt;/a&gt; 
        &lt;ul&gt;
          &lt;li&gt;&lt;a href="#HOperatingsystems"&gt;4.1 Operating systems&lt;/a&gt; 
      &lt;li&gt;&lt;a href="#HDongles"&gt;4.2 Dongles&lt;/a&gt; 
        &lt;/ul&gt;
          &lt;li&gt;&lt;a href="#HHintsforfutureimprovements"&gt;5 Hints for future improvements&lt;/a&gt; 
      &lt;/ul&gt; &lt;hr class="line"/&gt;
&lt;h3 class="heading-1-1"&gt;&lt;span id="HGoal"&gt;Goal&lt;/span&gt;&lt;/h3&gt;&lt;p class="paragraph"/&gt;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.&lt;p class="paragraph"/&gt;It uses the &lt;span class="wikiexternallink"&gt;&lt;a href="http://bluecove.org"&gt;&amp;#66;luecove JSR82 implementation&lt;/a&gt;&lt;/span&gt;, so all the device configuration may be done by setting Java system properties (see &lt;span class="wikiexternallink"&gt;&lt;a href="http://code.google.com/p/bluecove/wiki/Documentation"&gt;&amp;#116;he bluecove documentation&lt;/a&gt;&lt;/span&gt;).&lt;p class="paragraph"/&gt;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.
&lt;h3 class="heading-1-1"&gt;&lt;span id="HSampleusage"&gt;Sample usage&lt;/span&gt;&lt;/h3&gt; 
&lt;h4 class="heading-1-1-1"&gt;&lt;span id="HHowtostarttheserver"&gt;How to start the server&lt;/span&gt;&lt;/h4&gt;&lt;p class="paragraph"/&gt;&lt;div class="code"&gt;&lt;pre&gt;// Read properties and threads
BluetoothServerService m_server = &lt;span class="java&amp;#45;keyword"&gt;new&lt;/span&gt; BluetoothServerImpl();&lt;p class="paragraph"/&gt;// Set the device discoverable
m_server.prepareServer();&lt;p class="paragraph"/&gt;// Start listening in a special thread
m_server.startServer();&lt;/pre&gt;&lt;/div&gt;
&lt;h4 class="heading-1-1-1"&gt;&lt;span id="HHowtostoptheserver"&gt;How to stop the server&lt;/span&gt;&lt;/h4&gt;&lt;p class="paragraph"/&gt;&lt;div class="code"&gt;&lt;pre&gt;m_server.stop();&lt;/pre&gt;&lt;/div&gt;
&lt;h4 class="heading-1-1-1"&gt;&lt;span id="HHowtoconfiguretheserver"&gt;How to configure the server&lt;/span&gt;&lt;/h4&gt;&lt;p class="paragraph"/&gt;The server can be configured via a property XML file, given as an InputStream parameter to the prepareServer() method.&lt;p class="paragraph"/&gt;Sample : Read a configuration XML file embedded in the bundle JAR file.&lt;p class="paragraph"/&gt;&lt;div class="code"&gt;&lt;pre&gt;m_server.prepareServer(getClass().getResourceAsStream(&lt;span class="java&amp;#45;quote"&gt;"/bluetoothConfig.xml"&lt;/span&gt;));&lt;/pre&gt;&lt;/div&gt;&lt;p class="paragraph"/&gt;Parameters :&lt;p class="paragraph"/&gt;&lt;table class="wiki-table" cellpadding="0" cellspacing="0" border="0"&gt;&lt;tr&gt;&lt;th&gt;Key&lt;/th&gt;&lt;th&gt;Type&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;th&gt;Default&lt;/th&gt;&lt;/tr&gt;&lt;tr class="table-odd"&gt;&lt;td&gt;uuid&lt;/td&gt;&lt;td&gt;String&lt;/td&gt;&lt;td&gt;Server's "Universally" Unique IDentifier&lt;/td&gt;&lt;td&gt;&amp;#160;&lt;/td&gt;&lt;/tr&gt;&lt;tr class="table-even"&gt;&lt;td&gt;serviceName&lt;/td&gt;&lt;td&gt;String&lt;/td&gt;&lt;td&gt;Server's name&lt;/td&gt;&lt;td&gt;&amp;#160;&lt;/td&gt;&lt;/tr&gt;&lt;tr class="table-odd"&gt;&lt;td&gt;authenticate&lt;/td&gt;&lt;td&gt;boolean&lt;/td&gt;&lt;td&gt;Server needs client authentification&lt;/td&gt;&lt;td&gt;false&lt;/td&gt;&lt;/tr&gt;&lt;tr class="table-even"&gt;&lt;td&gt;encrypt&lt;/td&gt;&lt;td&gt;boolean&lt;/td&gt;&lt;td&gt;Communication must be encrypted&lt;/td&gt;&lt;td&gt;false&lt;/td&gt;&lt;/tr&gt;&lt;tr class="table-odd"&gt;&lt;td&gt;inquiryMode&lt;/td&gt;&lt;td&gt;int&lt;/td&gt;&lt;td&gt;Type of inquiries to respond to (GIAC or LIAC) (see &lt;span class="nobr"&gt;&lt;a href="http://bluecove.org/bluecove/apidocs/javax/bluetooth/DiscoveryAgent.html"&gt;&amp;#104;ttp://bluecove.org/bluecove/apidocs/javax/bluetooth/DiscoveryAgent.html&lt;/a&gt;&lt;/span&gt;)&lt;/td&gt;&lt;td&gt;GIAC&lt;/td&gt;&lt;/tr&gt;&lt;tr class="table-even"&gt;&lt;td&gt;debug&lt;/td&gt;&lt;td&gt;boolean&lt;/td&gt;&lt;td&gt;Verbose mode&lt;/td&gt;&lt;td&gt;false&lt;/td&gt;&lt;/tr&gt;&lt;tr class="table-odd"&gt;&lt;td&gt;readingMode&lt;/td&gt;&lt;td&gt;BYTE, CHAR or UTF&lt;/td&gt;&lt;td&gt;Which DataInputStream reading method must be used (readByte, readChar or readUTF)&lt;/td&gt;&lt;td&gt;CHAR&lt;/td&gt;&lt;/tr&gt;&lt;tr class="table-even"&gt;&lt;td&gt;max_threads&lt;/td&gt;&lt;td&gt;int&lt;/td&gt;&lt;td&gt;Maximum number of communication threads (not used)&lt;/td&gt;&lt;td&gt;&amp;#160;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;h4 class="heading-1-1-1"&gt;&lt;span id="HHowtoreaddatafromdevices"&gt;How to read data from devices&lt;/span&gt;&lt;/h4&gt;&lt;p class="paragraph"/&gt;This bundle use a listener model : each class who needs to read communication data must implement the CommunicationListener interface.&lt;p class="paragraph"/&gt;This interface provides three functions :
&lt;ul class="star"&gt;
&lt;li&gt;commBegin(String logicalName) : Called when a client has just connected the server, logicalName is UUID generated by the server to identify a connection&lt;/li&gt;
&lt;li&gt;commEnd(String logicalName) : Called when a client has ended the connection, or when the server stops.&lt;/li&gt;
&lt;li&gt;commRead(String logicalName, String data) : Called when the server read a line from the client.&lt;/li&gt;
&lt;/ul&gt;The logical name is the client unique identifier, based on its Bluetooth address and its friendly name (if present).&lt;p class="paragraph"/&gt;&lt;div class="code"&gt;&lt;pre&gt;class BluetoothComm &lt;span class="java&amp;#45;keyword"&gt;implements&lt;/span&gt; CommunicationListener &amp;#123;
  &lt;span class="java&amp;#45;keyword"&gt;private&lt;/span&gt; BluetoothServerService m_server;&lt;p class="paragraph"/&gt;  &lt;span class="java&amp;#45;keyword"&gt;public&lt;/span&gt; BluetoothComm()
    m_server = &lt;span class="java&amp;#45;keyword"&gt;new&lt;/span&gt; BluetoothServerImpl();
    m_server.prepareServer(getClass().getResourceAsStream(&lt;span class="java&amp;#45;quote"&gt;"/bluetoothConfig.xml"&lt;/span&gt;));
    m_server.startServer();
    m_server.addCommunicationListener(&lt;span class="java&amp;#45;keyword"&gt;this&lt;/span&gt;);
  &amp;#125;&lt;p class="paragraph"/&gt;  &lt;span class="java&amp;#45;keyword"&gt;public&lt;/span&gt; void commBegin(&lt;span class="java&amp;#45;object"&gt;String&lt;/span&gt; logicalName) &amp;#123;
    &lt;span class="java&amp;#45;object"&gt;System&lt;/span&gt;.out.println(&lt;span class="java&amp;#45;quote"&gt;"Client connected : "&lt;/span&gt; + logicalName);
  &amp;#125;&lt;p class="paragraph"/&gt;  &lt;span class="java&amp;#45;keyword"&gt;public&lt;/span&gt; void commEnd(&lt;span class="java&amp;#45;object"&gt;String&lt;/span&gt; logicalName) &amp;#123;
    &lt;span class="java&amp;#45;object"&gt;System&lt;/span&gt;.out.println(&lt;span class="java&amp;#45;quote"&gt;"Client gone : "&lt;/span&gt; + logicalName);
  &amp;#125;&lt;p class="paragraph"/&gt;  &lt;span class="java&amp;#45;keyword"&gt;public&lt;/span&gt; void commRead(&lt;span class="java&amp;#45;object"&gt;String&lt;/span&gt; logicalName, &lt;span class="java&amp;#45;object"&gt;String&lt;/span&gt; data) &amp;#123;
    &lt;span class="java&amp;#45;object"&gt;System&lt;/span&gt;.out.println(&lt;span class="java&amp;#45;quote"&gt;"Read '"&lt;/span&gt; + data + &lt;span class="java&amp;#45;quote"&gt;"' from "&lt;/span&gt; + logicalName);&lt;p class="paragraph"/&gt;    // Write some data in response
    &lt;span class="java&amp;#45;keyword"&gt;try&lt;/span&gt; &amp;#123;
      m_server.getCommunication(logicalName).writeData(&lt;span class="java&amp;#45;quote"&gt;"ACK&amp;#110;"&lt;/span&gt;);
    &amp;#125;
    &lt;span class="java&amp;#45;keyword"&gt;catch&lt;/span&gt; (IOException e) &amp;#123;
      // Error occurred during write process
    &amp;#125;
  &amp;#125;
&amp;#125;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 class="heading-1-1"&gt;&lt;span id="HIssuesunderLinux"&gt;Issues under Linux&lt;/span&gt;&lt;/h3&gt; 
&lt;h4 class="heading-1-1-1"&gt;&lt;span id="HLicenseissue"&gt;License issue&lt;/span&gt;&lt;/h4&gt; 
&lt;ul class="star"&gt;
&lt;li&gt;For latest versions BlueZ (v4 and higher), this bundle needs bluecove-gpl library to work, under GPL.&lt;/li&gt;
&lt;li&gt;For older versions, it &lt;strong class="strong"&gt;may&lt;/strong&gt; be possible to use bluecove-bluez instead, under Apache License 2.0 (&lt;strong class="strong"&gt;not tested&lt;/strong&gt;).&lt;/li&gt;
&lt;/ul&gt;&lt;h4 class="heading-1-1-1"&gt;&lt;span id="HRightsissue"&gt;Rights issue&lt;/span&gt;&lt;/h4&gt;&lt;p class="paragraph"/&gt;This bundle needs to have root rights in order to set the device discoverable.&lt;p class="paragraph"/&gt;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).
&lt;h3 class="heading-1-1"&gt;&lt;span id="HTest"&gt;Test&lt;/span&gt;&lt;/h3&gt; 
&lt;h4 class="heading-1-1-1"&gt;&lt;span id="HOperatingsystems"&gt;Operating systems&lt;/span&gt;&lt;/h4&gt; 
&lt;ul class="star"&gt;
&lt;li&gt;Windows&lt;ul class="star"&gt;
&lt;li&gt;Windows 7, 32 bits version&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Linux&lt;ul class="star"&gt;
&lt;li&gt;Fedora 13, 64 bits version, with bluecove-gpl&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;h4 class="heading-1-1-1"&gt;&lt;span id="HDongles"&gt;Dongles&lt;/span&gt;&lt;/h4&gt; 
&lt;ul class="star"&gt;
&lt;li&gt;Built-in AsusTEK bluetooth device, with generic drivers&lt;/li&gt;
&lt;/ul&gt;&lt;h3 class="heading-1-1"&gt;&lt;span id="HHintsforfutureimprovements"&gt;Hints for future improvements&lt;/span&gt;&lt;/h3&gt; 
&lt;ul class="star"&gt;
&lt;li&gt;Control the number of client threads, by aggregating them in a thread pool.&lt;/li&gt;
&lt;/ul&gt;
</renderedcontent>
</xwikidoc>