Skip to content
/ ble Public

Python interface to Bluetooth Low Energy devices with BlueZ.

License

Notifications You must be signed in to change notification settings

markrages/ble

Repository files navigation

ble

Pythonic interface to Bluetooth Low Energy on Linux+bluez.

I was not content with the API offered by the existing projects, so I added this layer on top.

Example

$ python
>>> import ble
>>> dev = ble.discover_device(lambda d: ble.uuids.heart_rate in d.uuids)
>>> dev.connect()
>>> dev.battery_service.battery_level.value
[100]
>>> dev.heart_rate_service.heart_rate_measurement.notifying=True
>>> print dev.heart_rate_service.heart_rate_measurement.value
{'hr': 97}

Backends

There are two interfaces to bluez that can be used. They are selected by editing the "ble.py" file.

  1. bluepy

    https://github.com/IanHarvey/bluepy

    bluepy uses the hci socket interface to bluez. This works well but it is deprecated and requires root access. bluepy uses a compiled helper application for this. To run bluepy as a non-root user, you can set that binary to be suid-root. I've included the script setup_helper.sh to accomplish this. Note that this is bad security practice. Don't make an installer that does this.

  2. dbus

    The other backend is shiny-new and crashes occasionally. Recent versions of bluez contain "GattService1" interfaces on the d-bus. So Python can directly control bluetooth without any shims or helper applications. To use this backend, download and compile bluez from the git repository. Then run bluetoothd with the experimental flag and plugins disabled.

    My Ubuntu uses an ancient version of bluez, so I just build a git pull.

    For Ubuntu 14.04, something like this works:

    $ git clone https://git.kernel.org/pub/scm/bluetooth/bluez.git
    $ cd bluez
    $ ./bootstrap
    $ ./configure --disable-systemd --enable-experimental
    $ make
    $ sudo -s  # "sudo service bluetooth stop" doesn't work
    # service bluetooth stop 
    # src/bluetoothd -p x -n -E # no plugins, no detach, experimental enabled
    

    Enable the dbus backend by editing ble.py. Maybe this will be runtime configurable in the future.

API

Services and characteristics are presented generically, but can be extended by adding a profile definition in profiles/. Any Python file in there is assumed to be profile definitions and will be loaded automatically when the associated UUID is encountered. Each service should be a class derived from ble.Service and each characteristic should be a class derived from ble.Characteristic. Any service or characteristic should have either a uuid class variable (to use an existing UUID) or a uuid_def class variable (to name a new UUID). See cps_service.py and dfu_service.py respectively for examples of the two declarations.

Bluetooth SIG defined UUID values are already named using the generated file uuids.json.

A characteristic is read and written using the property .value for reading and writing profile-interpreted data or .raw for reading and writing raw bytestrings. To receive notifications, set .notify to true. With notifications active, each read of .raw. or .value will present a new notificaion value. (The property .notify_timeout can be used to adjust the length of time for waiting for new values.)

Examples

There are two examples included in the distribution.

hr_client.py connects to a heart rate monitor, prints ten heart rate readings, then attemps to reset the energy integrator.

cps_client.py connects to a power meter, prints a single power notification, then does a calibration.

example_dfu.py connects to a Nordic Semiconductor nRF5x device with the Nordic DFU installed, then updates the application from the zipped firmware image prepared with nrfutil. This is a more complicated example, but the protocol is well-documented on the Nordic devzone website.

Hacking

uuids.json is generated by the script https://github.com/IanHarvey/bluepy/blob/master/bluepy/get_services.py

example_dfu.py reliably crashes git bluetoothd on my computer.

Using properties for non-idempotent things like reading successive notification feels like a weird API, but it's the closest mapping to the GATT API. But suggestions for a cleaner API are welcome.

About

Python interface to Bluetooth Low Energy devices with BlueZ.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published