Accessing the SoftDevice API from Python with pc-ble-driver-py

A new tool from Nordic has been released, pc-ble-driver-py, which allows Python developers to access the full SoftDevice 2.x.x API from a Python application.

Update: Raspberry Pi unofficial build available!

If you want to try version 0.5.0 on a Raspberry Pi, feel free to grab this build and give it a go! It is not officially supported by the driver and it's not on PyPi, but I am publishing it here in case it's of use to anyone at all.

pc_ble_driver_py_rpi-0.5.0.tar.gz

Overview

Features

The most prominent features of this package can be listed as:

  • Flexible modified BSD License to encourage contribution from the community
  • High-level abstraction of the SoftDevice API for Python developers (work in progress)
  • Thread-safe API with event queues for asynchronous operation
  • Optional auto-flashing of the connectivity firmware when loading the module
  • Robust J-Link CDC UART enumeration on all platforms
  • Support for both 32 and 64-bit Python 2.7.x on all major operating systems
  • Featured on the PyPI repository for simple installation
  • Ability to build the shared library from source with CMake for customisation
  • Ability to build the connectivity firmware based on the official SDK to port it to additional boards

Diagram

The following diagram depicts the overall architecture of the module and how it communicates with an nRF5x IC to expose the SoftDevice API to a Python application:

image description

Components

The main building blocks are:

  • The pc-ble-driver-py project on GitHub, which itself includes:
    • The Python high-level abstraction of the SoftDevice API in the form of the BLEDriver and BLEAdapter Python classes
    • The pc-ble-driver serialization library and serial port communication code, which is included as a Git submodule and is in itself a fully functional library accessible from any high-level language that has the capability of interfacing with C shared libraries, including of course C and C++.
    • The connectivity firmware (as part of pc-ble-driver), which includes both the connectivity app and the SoftDevice itself.

Requirements

To be able to use the package you require at the very least:

  • Python 2.7.x (32 or 64-bit) on any of the following platforms:
    • Windows (7 and newer)
    • Linux (Ubuntu 14.04 and 16.04 tested)
    • macOS (OS X), 10.11 "El Capitan" tested
  • An nRF51 or nRF52 DK board connected to the desktop with a USB cable

Additional tools and requirements are documented in the hardware setup section of the pc-ble-driver repository.

Installing the Python package

As described in the pc-ble-driver-py documentation you can simply install the package by using pip:

$ pip install pc-ble-driver-py

This will pull the dependencies and install the package in your local site-packages folder.

Running examples

In the examples folder of the installed package, or alternatively directly on GitHub you will find several Python scripts that make use of pc-ble-driver-py to achieve simple tasks such as enumerating all Segger J-Link serial ports, advertising or acting as a Hear Rate collector.

Note: Some of this examples initialize the BLEDriver class with auto_flash=True, which will trigger the automatic flashing of the connectivity firmware to the board specified via the serial port command-line option.

Contributing to the project

If you find this project interesting, we encourage you to contribute to it via the two GitHub repositories that contain the entirety of the source code:

  • The pc-ble-driver repository includes the C and C++ source code of the pc_ble_driver_shared shared library, which is used in turn by pc-ble-driver-py to communicate with the connectivity firmware running on the IC
  • The pc-ble-driver-py repository contains the Python abstraction layer, the SWIG file that exposes the C API of the shared library to be used from Python and the examples.

Happy coding!

Carles

  • @Carles are there any update regarding to Raspberry Pi? or how to use pc_ble_driver_py_rpi-0.5.0.tar.gz?

    Thanks

  • @Leon Why not hack it in Python and share the code with us? You will be properly credited and many other customers or tinkerers interested in the library will be able to benefit from it. As mentioned on the GitHub issue that mirrors these comments, we plan to expand the Python abstraction layers as time permits, but we will welcome any external contributions with open arms.

  • I second the request for a python (central role) example that parses any peripheral in a tree-like fashion, including support for 128-bit UUIDs, as a starting point for device-under-test (DUT) scenarios.

    Currently I am hacking the heart rate collector example in C.

  • Hi,

    Tried the examples and they do work as you mentioned in the post however these are very basic examples. Since there is no documentation / guide on how to use python library would appreciate if you could provide more examples. For e.g. I am looking for the ability to

    • issue scan of devices (your heart rate collector does this)
    • issue discovery of services (your heart rate kind of does this)
    • I want my app to be notified when the service discovery is done
    • Once discovery is done I want to have the handles of the characterisitics of various services. is there an event/callback that is fired when discovery process is done !!
    • Once I have the handle of the desired characteristics I want to perform read and write operations

    Would really appreciate an example like this.

    Regards & thanks Kapil