Control a Raspberry Pi with Android Over Bluetooth

Control a Raspberry Pi 3 Model BIf you wanted to build your own Android app to connect to a Python service, over Bluetooth, to control a Raspberry Pi, you just found the resources to do so. I know there are plenty of apps that control a Raspberry Pi. Most of them connect over SSH and some of them using Bluetooth. However, finding a tutorial that teaches you how to build your own is harder. You can probably do some research like I did and write an app but I haven’t managed to get the whole information in the same place.

Motivation

My aim is to share the knowledge I gathered and give you some basic source code that puts you on the right track. I will teach you how to write an easy to extend Python service and an Android app to connect to it. All the communication will happen over Bluetooth therefore removing the need of having a WiFi connection.
Also this article is the perfect place to get into Python Bluetooth programming. Also, at the same time you can get a glimpse about developing apps in Xamarin because the Android app is written using this platform.

You can get the whole source code for this project from my GitHub repo
https://github.com/levifuksz/raspibt

What do you need

For both the Python service and the Android app some basic coding skill is needed. I tried to keep the code easy to follow and well documented but a bit of understanding always helps. For the Python service part you can use your favorite editor to write the code. However, for the Android app you will need a bit more than that.

First of all you need Visual Studio IDE. You can fetch the 2017 Community version for free from the Microsoft website. Here is the link to it :
https://www.visualstudio.com/

Make sure that when you are installing Visual Studio 2017 you also install the Xamarin Platform as shown in the image below.

The Xamarin Platform also comes as a separate installer. This is useful when you already have Visual Studio 2017 installed or you have an older version. Grab the setup from:
https://www.xamarin.com/platform

Setting up the Raspberry Pi

Fire up a terminal and start by updating and upgrading the packages on your Raspbian

sudo apt-get update && sudo apt-get upgrade

The Python service uses the Pybluez extension and you can check it at.
https://karulis.github.io/pybluez/

Furthermore, Pybluez requires two additional software packages. These are the Python Development Library and the Bluetooth Development Library. You can get them both using:

sudo apt-get install python-dev libbluetooth-dev

You can install Pybluez using PIP, the Python package management system so just type:

sudo pip install pybluez

In addition, for the Python Bluetooth service to work, we will need to load the Serial Port Profile. This in turn requires the Bluetooth Daemon to run in compatibility mode. Start by editing the service startup parameters in its configuration file:

sudo nano /etc/systemd/system/dbus-org.bluez.service

Just add a -C after bluetoothd. The line should look like below:

ExecStart=/usr/lib/bluetooth/bluetoothd -C

Now reload the service configuration and restart the Bluetooth service with the following two commands

sudo systemctl daemon-reload
sudo systemctl restart dbus-org.bluez.service

Finally, you can now load the Serial Port profile by issuing:

sudo sdptool add SP

You should get a Serial Port service registered message as a result, telling you that the operation was successful.

The Python service explained

The service code in the raspibtsrv.py is pretty self explanatory.

Logging

The first few lines set up the logging for the script. Because our intention is to run this script as a service, all output needs to be written to files. The simplest way we can achieve this is by redirecting the Standard Output and Standard Error streams. The code from the setup_logging function starting on line 22 does exactly this. The logging was inspired by the article Stephen C. Phillips wrote at
Getting a Python script to run in the background (as a service) on boot

All output is saved to “/var/log/raspibtsrv.log” by default and can be changed with a script parameter. Log files are being rotated at midnight and only the last three log files are kept. The logger also appends the timestamp and the severity level for each message. Feel free to change this according to your needs.

Bluetooth setup

The “Control a Raspberry Pi” magic happens in the main function starting at line 70. The first few lines create a new Bluetooth socket using the RFCOM protocol and binds it to any available adapter and port.

# Create a new server socket using RFCOMM protocol
server_sock = BluetoothSocket(RFCOMM)
# Bind to any port
server_sock.bind(("", PORT_ANY))
# Start listening
server_sock.listen(1)

Because multiple Bluetooth “servers” may run on a single adapter there is a need to identify our service using something unique. This happens on lines 80 and 83. Here an UUID is advertised so any client knowing the UUID may connect. The same value for the service UUID is used in the Android app. Therefore, if you decide to change it please do it in both places.

# The service UUID to advertise
uuid = "7be1fcb3-5776-42fb-91fd-2ee7b5bbb86d"

# Start advertising the service
advertise_service(server_sock, "RaspiBtSrv",
				   service_id=uuid,
				   service_classes=[uuid, SERIAL_PORT_CLASS],
				   profiles=[SERIAL_PORT_PROFILE])
Receiving commands

The next step is to receive commands from the client. For each command do something specific and then respond to the client with a message. The list of the commands the script accepts is declared on line 90. There is also a special command, “getop”, that returns all supported commands to the client. Feel free to add more to suit your needs. Based on what the script receives on line 105 it acts starting from line 112. This is where you can add your own logic.

# Read the data sent by the client
data = client_sock.recv(1024)
if len(data) == 0:
	break

print "Received [%s]" % data

# Handle the request
if data == "getop":
	response = "op:%s" % ",".join(operations)
elif data == "ping":
	response = "msg:Pong"
elif data == "example":
	response = "msg:This is an example"
# Insert more here
else:
	response = "msg:Not supported"

client_sock.send(response)
print "Sent back [%s]" % response

Starting the Python service on boot

The next part of the tutorial assumes that the Python Bluetooth script is placed in a file named raspibtsrv.py at /home/pi/raspibtsrv/.

We want to control a Raspberry Pi over Bluetooth without any other interaction. Therefore our Python script containing the Bluetooth service needs to start on boot. The best way we can achieve this is by creating a systemd unit file that will execute our script.

Start by marking the Python script as executable

sudo chmod +x /home/pi/raspibtsrv/raspibtsrv.py

First of all, create the systemd unit file

sudo nano /etc/systemd/system/raspibtsrv.service

Paste in the following code (also changing paths if necessary)

[Unit]
Description=Raspberry PI Bluetooth Server
After=bluetooth.target

[Service]
Type=simple
User=root
Group=root
WorkingDirectory=/home/pi/raspibtsrv
ExecStart=/home/pi/raspibtsrv/raspibtsrv.py -l /home/pi/raspibtsrv/raspibtsrv.log

[Install]
WantedBy=multi-user.target

Now it is time to reload the systemd daemon configuration and enable the new service auto start.

sudo systemctl daemon-reload
sudo systemctl enable raspibtsrv.service

Finally, in order to check if everything is fine you need to reboot your Raspberry Pi.

sudo reboot

After the device has restarted check the status of the service using

sudo systemctl status raspibtsrv.service

Our service should be marked as active (running).
You can also check the log file to see if it got created. The log file should state that the Bluetooth service is listening.

cat /home/pi/raspibtsrv/raspibtsrv.log

The Android App

You can get the Android app that communicates with the Python service we just set up from
https://github.com/levifuksz/raspibt/tree/master/android-app

As I mentioned before, you need Visual Studio with Xamarin installed in order to compile the code. Just as the code in the Python service, the code from this app is also pretty well documented. Most of the things happen in two files: BtDiscovery.cs and BtClient.cs. Both are located under the Services folder in the RasPiBtControl.Android project.

The only thing you need to change is the Service UUID in Model\BtDeviceInfo.cs. This needs to match the UUID from the Pythons script. If you have not touched it then leave it unchanged here too.

The app only works if you have paired your phone with your Raspberry Pi, please do this first before using it.

Also, if you feel like extending the list of messages sent by the Python service that are supported by the app, update the LandingPageViewModel.cs file on line 168.

As a conclusion, there is no need for complicated solution to control a Raspberry Pi with your phone, all you need is a simple Python script and an even simpler app. Enjoy them both!

Further reading

To get a better hold on Python Bluetooth development take a look at this excellent tutorial written by Albert Huang from MIT:
An Introduction to Bluetooth Programming

Furthermore, read about unit files:
Understanding Systemd Units and Unit Files

Also, now that you can control a Raspberry Pi, turn it into a seedbox by following my other article
Turn your Raspberry Pi into a seedbox

T3ZlciBBbmQgT3V0IQ==

Recent Posts

Be First to Comment

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.