Bluetooth Programming in Python: Network Programming using RFCOMM

In the last article I discussed various Bluetooth profiles. If one wants to create a client-server based application using Bluetooth, then one should program for the RFCOMM profile. RFCOMM offers a socket-based client-server paradigm for providing services.

In this article, I will focus on creating networked based application using RFCOMM. The first section will be about the whys and wherefores of RFCOMM. In the second, third, and fourth sections, I will enumerate the steps necessary to create a client-server based application using RFCOMM. In the last section, a single-threaded server will be developed that uses RFCOMM to provide a file transfer service. That’s the outline for this discussion.

RFCOMM: The Whys and Wherefores

The term or abbreviation RFCOMM comes from the term "radio frequency" or RF. RFCOMM involves emulation of serial port communication using radio frequency, hence the name RFCOMM. The serial port emulated by RFCOMM is RS-232 which has 9 circuits. RFCOMM uses the baseband of Bluetooth to provide reliable and in-sequence delivery of a data stream. The main attributes of RFCOMM are:

  1. It provides multiple concurrent connections. It does this by relying on L2CAP. L2CAP can handle multiplexing over a single connection.
  2. It supports flow control on separate and individual channels.
  3. It does not provide error control. The assumption that RFCOMM makes is L2CAP provides an error-free channel. 
  4. How devices should communicate using RFCOMM is decided by the Serial Port Profile (SPP), which is one of the Bluetooth profiles.

RFCOMM divides devices into two major classes. They are Type I and Type II. The division is based on whether the port is physically present or emulated. I explain the details below.

Type I devices have emulated serial ports. Emulated ports are entities used to map system-specific services and their API to the RFCOMM services. Therefore, whenever applications are built for RFCOMM, Type I devices are used. In other words, Type I devices enable programmers to use serial port even if there is no physical serial port.

Type II devices have physical serial ports. They act as intermediate devices. In other words, they are proxies for relaying transmissions from RFCOMM to an external RS-232 interface that may be linked with other devices.

As I have said before, RFCOMM provides a client-server based paradigm. In the case of PyBluez, the client-server is based on sockets. And the steps to create them are similar to the steps that one would follow in creating TCP/IP or UDP- based sockets. The next section explains those steps. Let’s get started.

{mospagebreak title=Developing Applications for RFCOMM, Step by Step}

The steps necessary to develop RFCOMM-based applications can be divided into two main sets. They are creating the server and creating the client. Each of the steps can be again divided into sub-steps. Let us take each step one at a time.

Creating the Server

RFCOMM applications are essentially Bluetooth-based services. This has to be kept in mind when developing the server. The importance of this point will become clear in the steps regarding the client. Creating the server can be further divided into following steps:

  1. Creating the Server Socket
  2. Binding to a port
  3. Listening for requests
  4. Accepting the requests
  5. Sending data

The steps are same as that for creating a TCP/IP-based server. However, the first and last step differs for RFCOMM. The details are as follows.

Creating the Server Socket

The first step is to create the socket that will listen for and accept incoming requests and create the connection. The sockets one would use when working with RFCOMM are Bluetooth sockets. To create a Bluetooth socket, BluetoothSocket needs to be called with the protocol to be used. In this case the protocol is RFCOMM. So, to create a socket named server_socket the statement will be:

server_socket= Bluetooth.BluetoothSocket(Bluetooth.RFCOMM)


This statement only creates a simple Bluetooth-based socket that uses RFCOMM for communication. The next three steps make it a server socket.

Binding to a Port

This is the second step to making a simple socket work as a server socket. The socket object needs to be bound to an address and a port so that it can start listening for requests. However, since the socket will be communicating over Bluetooth, an IP address is not required. PyBluez will use the address of the device on which it is running. If the device is a desktop PC, then the address will correspond to the address provided by the Bluetooth adapter or dongle.

To bind a socket object to a port, the bind() method needs to be called on the socket object. The argument passed is a tuple containing the address and the port number with which the socket has to be bound. For example, to bind a socket to a port, say 11, the statement will be

server_socket.bind(("",11)) 

One point to keep in mind while working with RFCOMM is that RFCOMM uses ports between 1-30 only.

{mospagebreak title=Listening for requests}

Once a socket has been bound to a port, the next step is to make it listen for incoming requests. To do this, the listen() method needs to be called on the socket object. The listen() method accepts the number of requests to be kept in queue as the argument. For example, to make a socket start listening with a queue of size 3, the statement will be 

server_socket.listen(3)


Accepting the requests

Once a request is received, it has to be accepted so that communication can start. To do so, one has to call the accept() method on the socket object. The accept() method doesn’t have any arguments. It returns a tuple containing the address of the client and socket object through which further communication can be accomplished. So the statement to accept a connection is

client_socket,address=server_socket.accept()


Sending/receiving data

The last step is sending and/or receiving data. If the server is on a normal PC, then sending and receiving can be done using the Python library. However, if the server is on a smart phone, for example, then the library required will be based on the OS of the smart phone. For a normal PC, one would have to call send() and recv() methods on the socket object returned by the accept() method. Both accept strings as arguments. For example, if the server wants to send a message, say, "hello", the code will be

client_socket.send("Hello from server")

That completes the server part. Next comes the client.

{mospagebreak title=Developing the Client}

The steps necessary to developing the client are almost the same as those we needed to take to develop the server. The steps are

  1. Create a socket
  2. Connect to a device
  3. Sending/receiving data

The first and third steps are same as that of creating the server. So only the second step needs scrutinizing. I explain the details below.

Create a socket

Just as with a server socket, to create a client socket the BluetoothSocket() method needs to be called with RFCOMM as the protocol. So, to create a socket that would connect to a server, the statement will be

client_socket= Bluetooth.BluetoothSocket(Bluetooth.RFCOMM)


Connect to a device

To connect to a server, the client needs to know the address of the server. With Bluetooth, the address will be the address of the device, which is of the form "XX:XX:XX:XX:XX". So, to connect to a server running on a device with an address of "01:23:45:67:89:AB",  the connect() method needs to be called on the socket object with the port number and address of the server. For example, if the server port number is 4000 and the address is "01:23:45:67:89:AB", then the statement to connect to it is 

address="01:23:45:67:89:AB"

port=4000

client_sock.connect((address, port))


Sending/receiving data

At the client side too, the way to send and /or receive data is the same as that at the server side. So, to receive any data from the server, the statement would be

data = client_sockect.recv(1024)

print "received [%s]" % data


That completes the steps necessary to create a client and a server. Next, let us see how to develop a server that transfers a file using Bluetooth and RFCOMM.

{mospagebreak title=RFCOMM in the Real World}

The server will service only one client at a time. It is neither multithreaded nor multi-process based. Let us start. First comes the imports.

from bluetooth import *

Then comes the class that will contain the server functionalities. Its constructor will take the port number on which the server has to listen. It will also call the create_server function.

from bluetooth import *


class rfcomm_server:

def __init__(self,port):

self.port=port

self.create_server()

Next is the create_server method that will create a RFCOMM-based socket and make it listen on the passed port. It then calls the start_server method.

from bluetooth import *


class rfcomm_server:

def __init__(self,port):

self.port=port

self.create_server()


def create_server(self):

self.server_socket=

Bluetooth.BluetoothSocket(Bluetooth.RFCOMM)

 

self.server_socket.bind(("",self.port))

self.start_server()

Next is the start_server method. This method makes the server listen on the port and then starts the connection. After that it asks the user for the file and and then transfers it.

from bluetooth import *


class rfcomm_server:

def __init__(self,port):

self.port=port

self.create_server()


def create_server(self):

self.server_socket=

Bluetooth.BluetoothSocket(Bluetooth.RFCOMM)

 

self.server_socket.bind(("",self.port))

self.start_server()


def start_server(self):

while true:

self.server_socket.listen(3)

self.client_socket,address=server_socket.accept()

self.client_socket.send("Enter the file name")

file_name= self.client_socket.recv(2048)

 

if file_name is not None:

transfer_data=open(file_name,’r’).readlines()


for data in transfer_data:

self.client_socket.send(data)

 

self.client_socket.send("Transfer complete")

Next, let us start the server. To do that we first need to check whether the main function is being executed. If it is being executed, then we create the instance of the server.

from bluetooth import *


class rfcomm_server:

def __init__(self,port):

self.port=port

self.create_server()


def create_server(self):

self.server_socket=

Bluetooth.BluetoothSocket(Bluetooth.RFCOMM)

 

self.server_socket.bind(("",self.port))

self.start_server()


def start_server(self):

while true:

self.server_socket.listen(3)

self.client_socket,address=server_socket.accept()

self.client_socket.send("Enter the file name")

file_name= self.client_socket.recv(2048)

 

if file_name is not None:

transfer_data=open(file_name,’r’).readlines()


for data in transfer_data:

self.client_socket.send(data)

 

self.client_socket.send("Transfer complete")


if ‘__name__’==’__main__':

server=rfcomm_server(20)


That completes the application. It also brings us to the end of this discussion. The discussion until now has not touched upon the topic of service discovery. The next article will be about service discovery. Till then…

[gp-comments width="770" linklove="off" ]
antalya escort bayan antalya escort bayan