Running the Raspberry Pi as a Bluetooth Peripheral

From csn
Jump to navigation Jump to search

In this activity, we will set up the Raspberry pi to run a Bluetooth service as a peripheral device. Creating a GATT service and characteristic to write into. This is the way that devices like Fitbit or smartwatches communicate to your mobile phone, Using Characteristics to write data e.g the current time to the Fitbit or read information like a step count from the Fitbit. Characteristic types are read, write, and notify. Notify is similar to read but will tell the device connected e.g a mobile phone that it has new information. Today we will create a characteristic with only write.

Updating and installing the packages

Update your Raspberry Pi with:

sudo apt update

And then

sudo apt upgrade

We will now install the requirements for pybluez

sudo apt install python3-pip libbluetooth-dev git python3-dbus

We will then install the python packages:

sudo pip3 install pybluez RPi.GPIO

We are now going to modify the Bluetooth Service in the Raspberry Pi to turn on the Bluetooth service.

sudo nano /lib/systemd/system/bluetooth.service

Thet change the following line:

ExecStart=/usr/lib/bluetooth/bluetoothd

To

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

The -E flag enables experimental features. After adding the experimental flag to the raspberry pi we need to reboot the pi to enable this feature.

sudo reboot

After you have rebooted, log back into your Pi and return to the terminal.

Now we will use Git to download a package that has been written and use a modified version of one of the files to enable and disable a LED over Bluetooth.

git clone https://github.com/jay-donovan-murdoch/cputemp

cd into the folder we just downloaded on git

cd cputemp

Modifying the code

Edit the python3 script:

nano LEDscript.py

Then edit the code below. Ensure you change the text "IoT Murdoch" to a service name that is unique (otherwise you might connect to someone else’s pi by accident).

#!/usr/bin/env python3

#Python GATT server example for the Raspberry Pi
#Copyright (c) 2019, Douglas Otwell
#Distributed under the MIT license http://opensource.org/licenses/MIT


#BLE requiremetns
import dbus

from advertisement import Advertisement
from service import Application, Service, Characteristic, Descriptor

#GPIO Access
import RPi.GPIO as GPIO


GATT_CHRC_IFACE = "org.bluez.GattCharacteristic1"
NOTIFY_TIMEOUT = 5000

class LEDControlAdvertisement(Advertisement):
    def __init__(self, index):
        Advertisement.__init__(self, index, "peripheral")
        self.add_local_name("IoT Murdoch")
        self.include_tx_power = True

class BLEService(Service):
    MAIN_SVC_UUID = "00000001-710e-4a5b-8d75-3e5b444bc3cf"

    def __init__(self, index):

        Service.__init__(self, index, self.MAIN_SVC_UUID, True)
        self.add_characteristic(LEDControl(self))


class LEDControl(Characteristic):
    UNIT_CHARACTERISTIC_UUID = "00000002-710e-4a5b-8d75-3e5b444bc3cf"

    def __init__(self, service):
        Characteristic.__init__(
                self, self.UNIT_CHARACTERISTIC_UUID,
                ["write"], service)
        #self.add_descriptor(UnitDescriptor(self))

    def WriteValue(self, value, options):
        output = bytes(value).decode()
        if output == "0":
            print('turning LED off')
            GPIO.output(26,GPIO.LOW)
        elif output == "1":
            print('turning LED on')
            GPIO.output(26,GPIO.HIGH)
        else:
            print('try again')
            print(output)


#GPIO setup
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(26,GPIO.OUT)

app = Application()
app.add_service(BLEService(0))
app.register()

adv = LEDControlAdvertisement(0)
adv.register()

try:
    app.run()
except KeyboardInterrupt:
    app.quit()


The UUID which reads "00000001-710e-4a5b-8d75-3e5b444bc3cf" is a random identifier that you can generate here https://www.uuidgenerator.net/ general practice is for each characteristic under it to change the service UUID up by one.

128 bit identifiers are able to be used by anyone, you may see shorter ones on other devices these are locked to a specific vendor or a specific service e.g battery levels are 0x180F

Read more here https://www.bluetooth.com/specifications/gatt/services/

Now run the script

sudo python3 LEDscript.py

To connect we will use our mobile phone, download the app nRF Connect. This as available:

Using nRF Connect

Installing NRF
Installing NRF
Click Connect
Click Connect
Click Pair
Click Pair
Click the up arrow
Click the up arrow
Click UTF-8 and Write
Click UTF-8 and Write


Once open, search for the name you chose as a replacement for "IoT Murdoch" it will ask you to pair, swipe across to services in the app, then click the up arrow under your service

Then write into the service ensuring you select UTF-8 at the top, 1 means LED on, 0 means led off

You should then see the command line tell you that the LED is enabled, and it switch on

Final Pi Output
Final Pi Output

Wiring up the Pi and LEDs

In the code above we have set the script to use GPIO port 26 (37) and then use any ground port of the Raspberry Pi in our example, we will use port 38.

The code above will turn on the port when 1 is written and turn off the LED when 0 is written.


Connect these header pins to a breadboard with jumper wires. Then connect the LED to the breadboard ensuring that the polarity of the LED is correct. LEDs have to be connected in the correct way, the longer lead is the positive side and the shorter lead is the negative side.

Bluetooth and the Pi
Bluetooth and the Pi

Now run the script again and connect using nRF connect and see if the LEDs will now turn on and off.

sudo python3 LEDscript.py