How to configure Linux to act as a Bluetooth RFCOMM SPP server?

I'm writing a phone app for Android that connects to a bluetooth RFCOMM device in my car. My phone app talks AT commands with it. For development work, I often need to communicate with the device to try different commands and things.

My neighbors are starting to think I'm weird because I sit in my car for hours on end with my laptop screen shining on my face, typing away like a script kiddie.

I'd much rather configure one of my many Linux servers to act as a bluetooth RFCOMM device and allow me to connect to it (indoors, while I sit on my couch).

I imagine I have to start with something like sdptool add SP

But then what?

I'm perfectly happy writing a perl app to handle the I/O, but I just don't know how to make the bluez stack accept connections and subsequently pipe that stream to a perl app.


Solution 1:

Using Perl Net::Bluetooth looks promising... I'm playing with the following code, mostly copy and pasted from the examples, and cobbled together from various sources.

cat rfcomm-fake-server.pl

#! /usr/bin/perl -w

# Information Sources: 
# http://search.cpan.org/~iguthrie/Net-Bluetooth-0.40/Bluetooth.pm
# http://people.csail.mit.edu/albert/bluez-intro/x290.html#py-rfcomm-server-sdp
# http://people.csail.mit.edu/albert/bluez-intro/x232.html#rfcomm-server.py
# http://linuxdevcenter.com/pub/a/linux/2006/09/21/rediscovering-bluetooth.html?page=last


  use Net::Bluetooth;

  #### create a RFCOMM server

print "create rfcomm server\n";

  $obj = Net::Bluetooth->newsocket("RFCOMM");
  #### bind to port 1

print "binding to port 1\n";
  if($obj->bind(1) != 0) {
        die "bind error: $!\n";
  }

print "listening with backlog 2\n";
  #### listen with a backlog of 2
  if($obj->listen(2) != 0) {
        die "listen error: $!\n";
  }

print "register UUID\n";
  #### register a service
  #### $obj must be a open and bound socket
  # UUID Format: 00000000-0000-0000-0000-000000000000
  # RFCOMM:      00001101-0000-1000-8000-00805F9B34FB
  my $service_obj = Net::Bluetooth->newservice($obj, "00001101-0000-1000-8000-00805F9B34FB", "FAKEOBD", "Fake OBD Adapter");
print "Now what?\n";
  unless(defined($service_obj)) {
    print "There was a problem registering the UUID...\n";
    die ("Couldn't register UUID/service");
        #### couldn't register service
  }

  #### accept a client connection
print "Blocking until we receive an incoming connection";
  $client_obj = $obj->accept();
  unless(defined($client_obj)) {
        die "client accept failed: $!\n";
  }

  #### get client information
  my ($caddr, $port) = $client_obj->getpeername();

  print "Connected to $caddr on port $port\n";

  #### create a Perl filehandle for reading and writing
  *CLIENT = $client_obj->perlfh();
  print CLIENT "Hello there?";

while (<CLIENT>) {
    print "Data: "
}

Solution 2:

I tried the Perl Script by regulatre, but couldn't get it to work. The problem is that the Net::Bluetooth module doesn't register the class correctly with SDP.

Finally, I found this Java example that worked perfectly:

http://www.jsr82.com/jsr-82-sample-spp-server-and-client/

Note that it requires you to install the BlueCove jars on Linux. If your linux has the "bluez" stack, then you will need the two jars from BlueCove called

  • bluecove-version.jar
  • bluecove-gpl-version.jar

Solution 3:

Although this is a rather old question, the answer to "how to make the bluez stack accept connections and subsequently pipe that stream to a perl app" is rfcomm. You have to narrow down your SDP record to the specific channel you're about to use, e.g.:

sdptool add --channel 23 SP

Then run rfcomm like so (hci0 being the Bluetooth device of your choice):

rfcomm watch hci0 23 yourperlscript.pl {}

where {} will be replaced with the connected socket device, e.g. /dev/rfcomm0. By appending it to the invocation of yourperlscript.pl, that socket name will be passed as the first commandline argument to your script. I'm not too much into perl, but you should be able to create an object which is bound to the given device.