LightBlue: a cross-platform Python Bluetooth API

http://lightblue.sourceforge.net

Bea Lam <blammit@gmail.com>

This project is no longer maintained.

LightBlue is a cross-platform Bluetooth API for Python which provides simple access to Bluetooth operations. It is available for Mac OS X, GNU/Linux and Nokia's Python for Series 60 platform for mobile phones.

Downloads are available below, or see the sourceforge project page for the full list of downloads.

Features

LightBlue provides simple access to:

See the online API documentation for more details.

The Mac OS X implementation also introduces LightAquaBlue, an Objective-C framework that enables the implementation of custom OBEX clients and servers. See the LightAquaBlue documentation for more details.

LightBlue is released under the GPL v3 License.

Comments, suggestions, questions, etc. are most welcome and appreciated.


::: News :::

15 February, 09: Version 0.4 is out:

16 August, 08: Version 0.3.3 is out. This includes the following fixes:

March 21, 08: Version 0.3.2 is out. This includes some major bug fixes:

February 17, 08: Version 0.3.1 is out:

February 3, '08: Version 0.3 is out! The major features of this release are:

October 16, '07: Version 0.2.3 is out:

August 21, '07: Version 0.2.2 is out:

March 22, '07: Version 0.2.1 (intended to fix PyS60 build issues, but didn't)

March 6, '07: Version 0.2 has been released! The changes for this version are:


::: Downloads :::

For Mac OS X:

Requires Python 2.3 or later, and at least Xcode 2.1 and Mac OS 10.4 for building the included LightAquaBlue .xcodeproj package. (For Xcode 1.5 and Mac OS 10.3 you can create a .xcode project yourself and build that; see the readme for some tips.)

To install:

  1. If you have Mac OS 10.4 or earlier, install PyObjC (required by LightBlue to access Objective-C libraries). (PyObjC is built into Mac OS 10.5.)
  2. Download the LightBlue source files and extract them to some directory. Open a Terminal window, change to that directory, and run the command python setup.py install

Or, if you need to run with root access, use sudo python setup.py install instead.

Along with installing the LightBlue python library, this also installs the LightAquaBlue Objective-C framework into /Library/Frameworks/.

For Mac OS 10.6 users:

  1. Open src/mac/_lightblue.py and change signature="v@:@iB" to signature="v@:@iZ" (line 468)
  2. Download and unzip LightAquaBlue-python-MacOS10.6.zip, which contains a LightAquaBlue directory. Move this directory into your python site-packages library, e.g. /Library/Python/2.6/site-packages
  3. Download and unzip LightAquaBlue-framework-MacOS10.6.zip, which contains a (completely different) LightAquaBlue directory. Move this directory into src/mac to replace the existing src/mac/LightAquaBlue directory. This should fix the architecture/build problems that existed with the old LightAquaBlue xcode project.
  4. Run python setup.py install as per normal to install.

Some things to note:

For GNU/Linux:

Requires Python 2.3 or later, with the BlueZ bluetooth stack and development libraries. (Tkinter must be included with Python to call selectdevice() and selectservice().)

To install:

  1. First, install PyBluez (0.9 or later) and OpenOBEX (1.3 or later)
  2. Make sure you have installed the python development package for your distro (e.g. python-dev on ubuntu) or else you will get compile errors.
  3. Get the LightBlue source files, extract and run the usual python setup.py install (or with root access, sudo python setup.py install)

For Python for Series 60:

Requires Python for Series 60 to be installed on your phone. If you have a newer phone based on Series 60 3rd Edition FP1 or later, download it from the garage: Python for Series 60 project. Otherwise, get an older version from the Nokia PyS60 opensource page.

(If you don't know which S60 edition, Feature Pack etc. is the right one for your phone, see the wikipedia S60 entry.)

If you have Python for Series 60 1.9.x:

  1. Download the appropriate zip package for your phone:
  2. Unzip the files into your PyS60/dev-modules directory
  3. Use the PyS60 application manager to package your application with lighblue.

If you have Python for Series 60 1.4.x or earlier:

  1. Download the appropriate SIS installer file for your Series 60 phone:
  2. Send the SIS file to your phone via Bluetooth, then open it and install it as a library. (Or, use the Nokia PC Suite to install it.)

Please let me know if there are any problems with these builds, because it's impossible to test them for all the different editions.

If you're interested, the LightBlue source files (tar.gz or zip) include the python and C++ extensions source code as well as MMP files etc. for recompiling everything. For the 1.9.x builds, the files aren't in the tar/zip packages, but can be found in the svn repository.


::: Basic examples :::

Here are some examples of using the LightBlue API. Obviously, for the sake of simplicity, they assume lightblue has already been imported, like this:

    import lightblue
    

So to discover nearby devices and available services:

    >>> lightblue.finddevices()
    [('00:0E:6D:71:A2:0B', u'My6600', 5243396), ('00:0D:93:19:C8:68', 
    u'pantherbox', 1057028)]
    
    >>> lightblue.findservices('00:0D:93:19:C8:68')
    [('00:0D:93:19:C8:68', 10, 'OBEX Object Push'), ('00:0D:93:19:C8:68', 15, 
    'OBEX File Transfer'), ('00:0D:93:19:C8:68', 1, 'Bluetooth-PDA-Sync'),
    ('00:0D:93:19:C8:68', 3, 'Palm Serial Port')]

To ask the end user to select a device or service:

    >>> lightblue.selectdevice()      # brings up a device-selection GUI 
    ('00:0E:6D:71:A2:0B', u'My6600', 5243396)
    
    >>> lightblue.selectservice()     # brings up a service-selection GUI 
    ('00:0E:6D:71:A2:0B', 2, u'Bluetooth Serial Port')
    

To use RFCOMM socket objects:

    # client socket
    >>> s = lightblue.socket()
    >>> s.connect(("00:12:2c:45:8a:7b", 5))
    >>> s.send("hello")
    5
    >>> s.close()
    
    # server socket
    >>> s = lightblue.socket()
    >>> s.bind(("", 0))  # bind to 0 to bind to dynamically assigned port 
    >>> s.listen(1)
    >>> lightblue.advertise("My RFCOMM Service", s, lightblue.RFCOMM)
    >>> conn, addr = s.accept()
    >>> print "Connected by", addr
    Connected by ('00:0D:93:19:C8:68', 5)   
    >>> conn.recv(1024)
    "hello"
    >>> conn.close()
    >>> s.close()

To send and receive files over OBEX:

    # send a file (can pass file name or file object)
    >>> lightblue.obex.sendfile("00:12:2c:45:8a:7b", 10, "MyFile.txt")
    
    # receive a file and save it as MyFile.txt
    >>> s = lightblue.socket()
    >>> s.bind(("", 0))
    >>> lightblue.advertise("My OBEX Service", s, lightblue.OBEX)
    >>> lightblue.obex.recvfile(s, "MyFile.txt")  # or pass file object instead
    >>> s.close()
    

To run OBEX client sessions:

    # send a business card (vCard) to an Object Push service
    >>> client = lightblue.obex.OBEXClient("00:12:2c:45:8a:7b", 10)
    >>> client.connect()
    <OBEXResponse reason='OK' code=0x20 (0xa0) headers={}>
    >>> client.put({"name": "MyBusinessCard.vcf"}, file("MyBusinessCard.vcf", "r"))
    <OBEXResponse reason='OK' code=0x20 (0xa0) headers={}>
    >>> client.disconnect()
    <OBEXResponse reason='OK' code=0x20 (0xa0) headers={}>
    
    # get a directory listing from a File Transfer service
    # (see examples/obex_ftp_client.py for a basic File Transfer client implementation)
    >>> client = lightblue.obex.OBEXClient("00:12:2c:45:8a:7b", 15)
    >>> ftp_target_uuid = '\xf9\xec{\xc4\x95<\x11\xd2\x98NRT\x00\xdc\x9e\t'
    >>> client.connect({"target": ftp_target_uuid})
    <OBEXResponse reason='OK' code=0x20 (0xa0) headers={'connection-id': 327258,
    'who': '\xf9\xec{\xc4\x95<\x11\xd2\x98NRT\x00\xdc\x9e\t'}>
    >>> import StringIO
    >>> dirlist = StringIO.StringIO()
    >>> client.get({'type': 'x-obex/folder-listing'}, dirlist)
    <OBEXResponse reason='OK' code=0x20 (0xa0) headers={'length': 292}>
    >>> dirlist.getvalue()
    '<?xml version="1.0"?>\n<!DOCTYPE folder-listing SYSTEM 
    "obex-folder-listing.dtd"\n  [ <!ATTLIST folder mem-type CDATA #IMPLIED>\n  
    <!ATTLIST folder label CDATA #IMPLIED> ]>\n<folder-listing version="1.0">\n   
    <folder name="C:" user-perm="RW" mem-type="DEV" label="Phone memory"/>\n</folder-listing>'
    >>> client.disconnect()
    <OBEXResponse reason='OK' code=0x20 (0xa0) headers={}> 
        

To read local device information:

    >>> lightblue.gethostaddr()
    '00:0F:3D:5F:20:F0'
    >>> lightblue.finddevicename(lightblue.gethostaddr())  # get local device name
    u'susebox'
    >>> lightblue.gethostclass()    # class of device
    3670276

::: Other notes :::

Implementation

LightBlue's implementation uses native and third-party libraries on the three platforms, including:

Current limitations