Setup Docker

raspberry pi, docker and application system diagram

We're going to install Docker on the Raspberry Pi, but why would we do that? Dependency management was the hardest part of this project, so Docker is going to keep us sane. In order for a Python application to send messages over D-Bus it needs access to the type definitions in the glib package. Finding the right system packages and python libraries that were all compatible was a balancing act. On top of that, the Raspberry Pi isn't an x86 architecture machine (it's an ARMv6), so packages are a little harder to find.

At the end we're going to download a docker image that has all the dependencies already compiled and installed for Raspberry Pi, so you can skip this section if you want to.


Install Docker

Run the following commands on the Raspberry Pi to get docker installed:

 # install docker on the Raspberry Pi
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker pi
sudo reboot  

Get the Container

Pull down the Docker image with dependencies pre-built for the Raspberry Pi's architecture

 # pull down the image
docker pull soodesune/python3-bluetooth  

Working with the Docker Image

Our system is setup to isolate the radios, hardware, and "firmware" from the application run-time and the application code:

  • The Raspberry Pi has one radio, which happens to be integrated into it's CPU. This is where code gets converted into radio waves and needs to deal with real-world problems, like how to represent a number (our temperature) as a series of electromagnetic waves. For a fulsome explanation of the physics of Bluetooth, see NovelBits.io
  • The Raspberry Pi 3 model B ships with the Bluetooth drivers to make the radio work, this is the Bluez 5.50 software package.
  • Your application communicates with BlueZ by using the D-Bus "system bus". D-Bus is a Linux system that allows processes to communicate with each other by connecting to the D-Bus socket(file)- where messages can be sent/received. In order for our Docker run-time to communicate with D-Bus we'll need to mount the D-Bus socket to our container with Docker's --volume command. More detail on this in a later section
  • Our application code is going to live on the Raspberry Pi host operating system, so that it's easy to edit, but we're also going to --volume mount it to the Docker container so that the Python 3 run-time (and installed dependences) have access to it.

You can skip ahead now, the rest of this section is an explanation of dependencies installed on the container. You won't need to know this to get the project working.

Next

Understand the Dependencies

The two main dependencies are glib installed from apt-get and the python library dasbus. Most of the Python 3 sample code for working with D-Bus, like the dbus-python package, are unmaintained and I wasn't able to find the system libraries that they require. Literally every post I found online about how to work with Bluetooth in Python was using the sample code from BlueZ, which uses dbus-python.

My Dockerfile may have a few unneeded installs, but it ended up looking like this:

 FROM python:3.8.3

RUN apt-get update

RUN apt-get install -y --no-install-recommends libboost-all-dev
RUN apt-get install -y bluez \
  bluetooth \
  pkg-config \
  libboost-python-dev \
  libboost-thread-dev \
  libbluetooth-dev \
  libglib2.0-dev \
  python3-dev \
  libgirepository1.0-dev \
  gcc \
  libcairo2-dev \
  gir1.2-gtk-3.0

RUN pip3 install --upgrade pip
RUN pip3 install pycairo PyGObject dasbus

ENTRYPOINT ["python"]  

If you're going to build this yourself, you need to do it on the Raspberry Pi (as opposed to your laptop). If you build on an x86 machine, the resulting Docker image won't run on the Pi.

Next