Python and
|
Modified: |
Resources
Bluetooth is a wireless protocol for local communications.
Python is a simple but powerful language that comes with many of the fundamental tools needed for quickly programming locally networked applications.
While many similarities exist between Internet and Bluetooth protocols, one key difference is that Bluetooth devices move in and out of radio frequency range. Normally, before commencing communication, devices must discovery others to detect the address and services that are provided by other devices.
Bluetooth Stack ![]()
Microsoft Vista provides a Bluetooth stack that can enabled through the Control Panel.
Broadcom devices, such as those in LF115, are also supported by the more reliable and robust Widcomm drivers.
Windows Bluetooth programming
PyBluez
A Python Bluetooth library for the Windows and GNU/Linux operating systems. Mac OSX and Linux Python are supported by LightBlue, a number of cell phones running the Symbian OS are supported under Python. The following examples use the PyBluez bluetooth library.
Discovery
The address and name of enabled devices within range can be discovered by other Bluetooth devices. Discovery can take some time to complete, given that radio communications is unreliable. The following displays address and name of all enabled devices nearby.
from bluetooth import *
print "performing inquiry..."
nearby_devices = discover_devices(lookup_names = True)
print "found %d devices" % len(nearby_devices)
for name, addr in nearby_devices:
print " %s - %s" % (addr, name)performing inquiry...
found 2 devices
Ray's Nokia - 00:12:D2:5A:BD:E4
Ray's MacBook - 00:1E:C2:93:DA:6FRFCOMM service
Because RFCOMM is a connection-oriented protocol, similar to TCP, one process acts as a server accepting connections, another process acts as the client requesting the connection.
Below are basic client and server scripts, to keep things simple, we manually entered the Bluetooth device address (00:12:D2:5A:BD:E4) of the server (much like with the Internet) and a port; in the following, the client connects to the server on port 3.
Note: in the Client below, when connected to a server on a Nokia cell-phone, closing the client_socket immediately after sending data may result in a run-time error on the server. The client print statement adds time to prevent an immediate client close that would cause the server to occasionally crash!
Client
from bluetooth import *
# Create the client socket
client_socket=BluetoothSocket( RFCOMM )
client_socket.connect(("00:12:D2:5A:BD:E4", 3))
client_socket.send("Hello World")
print "Finished"
client_socket.close()Server
from bluetooth import *
server_socket=BluetoothSocket( RFCOMM )
server_socket.bind(("", 3 ))
server_socket.listen(1)
client_socket, address = server_socket.accept()
data = client_socket.recv(1024)print "received [%s]" % data
client_socket.close()
server_socket.close()
Try Note that only one instance of IDLE can be open at a time.
- Save the above files as:
- client.py
- server.py
- Open two Command Prompt windows.
- Change the directory to the location of the Python files.
- Enter:
- python server.py
- python client.py
- import bluetooth - the Bluetooth library containing all the necessary function definitions.
- client_socket=BluetoothSocket( RFCOMM ) - Constructs a socket for RFCOMM service.
- client_socket.connect(("00:12:D2:5A:BD:E4", 3)) - Client requests a connection with host 00:12:D2:5A:BD:E4 on port 3.
- server_socket.bind(("",3)) - Server binds the script on host '' to port 3.
- server_socket.listen(1) - Server listens to accept 1 connection at a time.
- client_socket, address = server_socket.accept() - Server accepts connection request from a client; client_socket is the socket used for communication with client and address the client's address.
- client_socket.send('Hello world') - Send a string through the socket client_socket.
- data = server_socket.recv(1024) - Receive data through socket server_socket, assign to variable data; a maximum of 1024 characters received at a time.
- server_socket.close() - Close the connection on socket server_socket.
Example: Echo client and server
# echoclient.py import sys from bluetooth import * HOST = sys.argv[1] # The remote host PORT = 8888 # Server port
s=BluetoothSocket( RFCOMM )
s.connect((HOST, PORT)) while True : message = raw_input('Send:') if not message : break s.send(message) data = s.recv(1024) print 'Received', `data` s.close() # echoserver.py from bluetooth import * HOST = '' # Symbolic name PORT = 8888 # Non-privileged ports=BluetoothSocket( RFCOMM )s.bind((HOST, PORT)) s.listen(1) conn, addr = s.accept() print 'Connected by', addr while True: data = conn.recv(1024) if not data: break conn.send(data) conn.close()
Try Note that only one instance of IDLE can be open at a time.
- Save the above files as:
- client.py
- server.py
- Open two Command Prompt windows.
- Change the directory to the location of the Python files.
- Enter the following, note the address of the server is read from the command line:
- python echoserver.py
- python echoclient.py 00:12:D2:5A:BD:E4
Example: echoclient and echoserver as functions
# echoclient.pyimport sys from bluetooth import * def client( host, port) : s=BluetoothSocket( RFCOMM )
s.connect((host, port)) while True : message = raw_input('Send:') if not message : return s.send(message) data = s.recv(1024) print 'Received', `data` s.close()client(sys.argv[1], 8888)# echoserver.py from bluetooth import * def server( s ) : conn, addr = s.accept() print 'Connected by', addr while True: data = conn.recv(1024) if not data: break conn.send(data) conn.close()s=BluetoothSocket( RFCOMM ) s.bind(('', 8888)) s.listen(1) server( s )
Using Service Discovery Protocol (SDP)
We have seen that Bluetooth devices can locate other nearby devices, those that are in discovery mode. Rather than connecting by the address and port of a device and application, devices can discover the address and port by the service name.
The following versions perform the same function, sending 'Hello world' from a client to a server, as earlier examples but using SDP. On the server-side, the primary use of SDP to advertise the helloService as a serial port or RFCOMM protocol.
The client first finds a list of devices that provide the helloService (in reality, more than just helloService is returned). The list is then searched for the helloService, when found, the associated host address and port are used to connect to the service.
Client
from bluetooth import *
services=find_service(name="helloService",
uuid=SERIAL_PORT_CLASS)
for i in range(len(services)):
match=services[i]
if(match["name"]=="helloService"):
port=match["port"]
name=match["name"]
host=match["host"]
print name, port, host
client_socket=BluetoothSocket( RFCOMM )
client_socket.connect((host, port))
client_socket.send("Hello world")
client_socket.close()
breakServer
import bluetooth
server_sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )
server_sock.bind(("",bluetooth.PORT_ANY))
server_sock.listen(1)
bluetooth.advertise_service(server_sock, "helloService",
service_classes=[bluetooth.SERIAL_PORT_CLASS],
profiles=[bluetooth.SERIAL_PORT_PROFILE])
client_sock, address = server_sock.accept()
print "Accepted connection from ",address
data = client_sock.recv(1024)
print "received [%s]" % data
client_sock.close()
server_sock.close()
Try Note that PyBluez does not discover services using the Widcomm stack nor is an address of 'localhost' allowed.
The following assumes using the two PCs as client and server.
- Save the above helloServiceClient.py file and the PyBluez helloServiceServer.py file to different PCs.
- Run the helloServiceServer.py file.
- Run the helloServiceClient.py file.
- server_sock.bind(("",bluetooth.PORT_ANY)) - Server binds the script on host '' to a dynamically assigned port.
- bluetooth.advertise_service(server_sock, "helloService", service_classes=[bluetooth.SERIAL_PORT_CLASS], profiles=[bluetooth.SERIAL_PORT_PROFILE]) - The service name is 'helloService' as a SERIAL_PORT_CLASS or RFCOMM.
Symbian Bluetooth programming
Python S60
Python includes a Bluetooth library on the Symbian S60 operating systems. The following examples use Python for the Symbian OS.
Discovery
The address, services and ports used of enabled devices within range can be discovered by other Bluetooth devices. When the following script is run, device names are automatically displayed. The selected device address, services and ports are then displayed.
Note that the results can be erratic, even crashing the Python interpreter.
import socket
print "\n\nperforming inquiry..."
address, services = socket.bt_discover()
print "Address: %s" % address
for name, port in services.items():
print u"%s : %d" % (name, port)
RFCOMM service
Because RFCOMM is a connection-oriented protocol, similar to TCP, one process acts as a server accepting connections, another process acts as the client requesting the connection.
Below are basic client and server scripts, to keep things simple, we manually entered the Bluetooth device address (00:12:D2:5A:BD:E4) of the server (much like with the Internet) and a port; in the following, the client connects to the server on port 3. The address and serial port number can be determined by running the above discovery script.
Client
import socket
client_socket=socket.socket(socket.AF_BT,socket.SOCK_STREAM)
client_socket.connect(("00:18:F8:89:8B:A5",1))
client_socket.send("Hello World")
client_socket.close()Server
import socket
server_socket=socket.socket(socket.AF_BT, socket.SOCK_STREAM)
socket.set_security(server_socket, socket.AUTH)
port = socket.bt_rfcomm_get_available_server_channel(server_socket)
server_socket.bind(("", port))
server_socket.listen(1)
client_socket, address = server_socket.accept()
data = client_socket.recv(1024)
print "received [%s]" % data
client_socket.close()
server_socket.close()
Try Note that only one instance of Python can be open at a time on the phone.
The following assumes using the phone as client and a PC as server.
- Modify the address in client.py file to that of the PC Bluetooth device.
- Save the above client.py file to the phone and the PyBluez server.py file to a PC.
- Start Python on the phone and IDLE on the PC.
- Change to the PC directory to the location of the Python server.py file.
- On PC, enter:
- python server.py
- On the phone, choose Option and Run Script, selecting client.py file.
- import socket - the Bluetooth library is part of the socket library.
- client_socket=socket.socket(socket.AF_BT,socket.SOCK_STREAM) - Constructs a socket for RFCOMM service.
- client_socket.connect(("00:12:D2:5A:BD:E4", 1)) - Client requests a connection with host 00:12:D2:5A:BD:E4 on port 1.
- socket.set_security(server_socket, socket.AUTH) - Authorize security access.
- port = socket.bt_rfcomm_get_available_server_channel(server_socket) - Get an available port.
- server_socket.bind(("", port)) - Server binds the script on host '' to port.
- server_socket.listen(1) - Server listens to accept 1 connection at a time.
- client_socket, address = server_socket.accept() - Server accepts connection request from a client; client_socket is the socket used for communication with client and address the client's address.
- client_socket.send('Hello world') - Send a string through the socket client_socket.
- data = server_socket.recv(1024) - Receive data through socket server_socket, assign to variable data; a maximum of 1024 characters received at a time.
- server_socket.close() - Close the connection on socket server_socket.