Python-Bluezero Documentation: Release 0.0.4
Python-Bluezero Documentation: Release 0.0.4
Release 0.0.4
1 Overview 1
1.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
2 Examples 3
2.1 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
3 Installing Bluez 13
3.1 Installing Bluez . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
4 python-bluezero modules 17
4.1 python-bluezero Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
i
ii
CHAPTER 1
Overview
Overview
Bluetooth
Bluetooth is a standard set of binary protocols for short-range wireless communication between devices.
• Bluetooth “Classic” (BR/EDR) supports speeds up to about 24Mbps.
• Bluetooth 4.0 introduces a low energy mode, “Bluetooth Low Energy” (BLE or LE, also known as “Bluetooth
Smart”), that operates at 1Mbps. This mode allows devices to leave their transmitters off most of the time. As
a result it is “Low Energy”.
BLE functionality is dominated by key/value pairs that create a Generic Attribute Profile (GATT).
BLE defines multiple roles that devices can play:
• The Broadcaster (beacon) is a transmitter only application.
• The Observer (scanner) is for receiver only applications.
• Devices acting in the Peripheral role can receive connections.
• Devices acting in the Central role can connect to Peripheral devices.
1
python-bluezero Documentation, Release 0.0.4
BlueZ
BlueZ is a Bluetooth stack for the Linux family of operating systems. Support for BlueZ can be found in many Linux
distributions available.
The highest level of API on BlueZ is the DBus API which can be daunting to users unfamiliar with such APIs.
python-bluezero offers users a more gentle learning curve to using Bluetooth functionality on Linux.
This section gives guidelines about the complexity of different python-bluezero APIs. We will use the terms
Level 1, 10 and 100. A new user would start at Level 1 as this should offer the least friction. If at a later stage a greater
level of control is needed then the user can progress on to the other levels. As the user becomes more experienced they
may not need Bluezero and will use BlueZ on its own. The numbers for the API levels represent the steps in code and
knowledge required with each step.
Level 1
Level 10
Level 100
• At this level the interface is expecting the user to know Bluetooth, DBus and event loops.
• DBus function names are not Pythonic but will be exposed at the level.
• This level will be very specific to the Linux kernel and so it will be difficult to port this to other operating
systems that do not have the Bluez Daemon running.
• The previous more abstracted API levels should be easier to port to any hardware.
2 Chapter 1. Overview
CHAPTER 2
Examples
Examples
Level 1
Adapter
This example prints out the status of the Bluetooth device on your Linux computer. It also checks to see if it is enabled
(powered) before scanning for nearby Bluetooth devices:
from bluezero import adapter
def main():
dongles = adapter.list_adapters()
print('dongles available: ', dongles)
dongle = adapter.Adapter(dongles[0])
3
python-bluezero Documentation, Release 0.0.4
if __name__ == '__main__':
main()
This example broadcasts a given URL in a format for the Physical Web:
from bluezero import eddystone
eddystone.EddystoneURL('https://github.com/ukBaz')
Level 10
Micro:bit Buttons
This example reads the status of the buttons on a BBC micro:bit and indicates them on a Ryanteck Traffic Hat. (To
run this replace xx:xx:xx:xx:xx:xx with the address of your micro:bit):
python3 microbit_button.py xx:xx:xx:xx:xx:xx
"""
This is a simple example of how to read data from a micro:bit.
This code was developed using the 'Bluetooth Most Services, No Security'
micro:bit hex file from:
http://bluetooth-mdw.blogspot.co.uk/p/bbc-microbit.html
"""
import argparse
import dbus
from time import sleep
# constants
led1 = LED(22)
led2 = LED(23)
led3 = LED(24)
buzz = Buzzer(5)
BEEP_TIME = 0.25
class microbit:
"""
Class to introspect Bluez to find the paths for required UUIDs
"""
4 Chapter 2. Examples
python-bluezero Documentation, Release 0.0.4
def connect(self):
self.remote_device_methods.Connect()
while not self.remote_device_props.Get(
constants.DEVICE_INTERFACE,
'ServicesResolved'):
sleep(0.25)
self._update_dbus_paths()
def _update_dbus_paths(self):
self.btn_srv_path = tools.uuid_dbus_path(constants.GATT_SERVICE_IFACE,
self.btn_srv_uuid)[0]
# Button A
self.btn_a_chr_path = tools.uuid_dbus_path(constants.GATT_CHRC_IFACE,
self.btn_a_chr_uuid)[0]
# Button B
self.btn_b_chr_path = tools.uuid_dbus_path(constants.GATT_CHRC_IFACE,
self.btn_b_chr_uuid)[0]
@property
def connected(self):
"""Indicate whether the remote device is currently connected."""
return self.remote_device_props.Get(
constants.DEVICE_INTERFACE, 'Connected')
def disconnect(self):
self.remote_device_methods.Disconnect()
def read_button_a(self):
"""
Helper function to read the state of button A on a micro:bit
:return: integer representing button value
"""
return self.read_button(self.btn_a_chr_path)
2.1. Examples 5
python-bluezero Documentation, Release 0.0.4
def read_button_b(self):
"""
Helper function to read the state of button B on a micro:bit
:return: integer representing button value
"""
return self.read_button(self.btn_b_chr_path)
def central(address):
dongle = adapter.Adapter(adapter.list_adapters()[0])
if not dongle.powered:
dongle.powered = True
# Find nearby devices
dongle.nearby_discovery()
ubit = microbit(address)
sense_buttons = True
ubit.connect()
led2.on()
buzz.on()
sleep(BEEP_TIME)
buzz.off()
while sense_buttons:
btn_a = ubit.read_button_a()
btn_b = ubit.read_button_b()
# print('Button states: a={} b={}'.format(btn_a, btn_b))
if btn_a > 0 and btn_b < 1:
print('Button A')
led1.on()
led3.off()
elif btn_a < 1 and btn_b > 0:
print('Button B')
led1.off()
led3.on()
elif btn_a > 0 and btn_b > 0:
6 Chapter 2. Examples
python-bluezero Documentation, Release 0.0.4
sense_buttons = False
led1.on()
led3.on()
buzz.on()
sleep(BEEP_TIME)
buzz.off()
print('Bye bye!!!')
elif btn_a < 1 and btn_b < 1:
led1.off()
led3.off()
if not ubit.connected:
sense_buttons = False
led1.on()
led2.on()
led3.on()
buzz.on()
sleep(BEEP_TIME)
buzz.off()
sleep(0.02)
# Disconnect device
ubit.disconnect()
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='Use micro:bit as remote for Ryanteck TrafficHAT.')
parser.add_argument('address',
help='the address of the micro:bit of interest')
args = parser.parse_args()
central(str(args.address))
TI CC2650
This example reads the sensors or buttons on a TI SensorTag and prints them out to the screen:
"""
This is a simple example of how to read the Ti Sensortag CC2650.
2.1. Examples 7
python-bluezero Documentation, Release 0.0.4
def client():
dongle = adapter.Adapter(adapter.list_adapters()[0])
if not dongle.powered:
dongle.powered = True
dongle.nearby_discovery()
cc2650 = device.Device(tools.device_dbus_path(constants.DEVICE_INTERFACE,
'SensorTag')[0])
# Connect to device
cc2650.connect()
8 Chapter 2. Examples
python-bluezero Documentation, Release 0.0.4
# constants
TMP_CONF_PATH = Characteristic(tools.uuid_dbus_path(
constants.GATT_CHRC_IFACE,
'F000AA02-0451-4000-B000-000000000000')[0])
TMP_DATA_PATH = Characteristic(tools.uuid_dbus_path(
constants.GATT_CHRC_IFACE,
'F000AA01-0451-4000-B000-000000000000')[0])
OPT_CONF_PATH = Characteristic(tools.uuid_dbus_path(
constants.GATT_CHRC_IFACE,
'F000AA72-0451-4000-B000-000000000000')[0])
OPT_DATA_PATH = Characteristic(tools.uuid_dbus_path(
constants.GATT_CHRC_IFACE,
'F000AA71-0451-4000-B000-000000000000')[0])
BAR_CONF_PATH = Characteristic(tools.uuid_dbus_path(
constants.GATT_CHRC_IFACE,
'F000AA42-0451-4000-B000-000000000000')[0])
BAR_DATA_PATH = Characteristic(tools.uuid_dbus_path(
constants.GATT_CHRC_IFACE,
'F000AA41-0451-4000-B000-000000000000')[0])
HUM_CONF_PATH = Characteristic(tools.uuid_dbus_path(
constants.GATT_CHRC_IFACE,
'F000AA22-0451-4000-B000-000000000000')[0])
HUM_DATA_PATH = Characteristic(tools.uuid_dbus_path(
constants.GATT_CHRC_IFACE,
'F000AA21-0451-4000-B000-000000000000')[0])
# Disconnect device
cc2650.disconnect()
if __name__ == '__main__':
client()
Level 100
2.1. Examples 9
python-bluezero Documentation, Release 0.0.4
This example advertises a Physical Web Beacon using the Eddystone standard. Currently this can only be connected
to by the Physical Web app because that is the only thing that supports FatBeacons:
FAT_SERVICE = 'AE5946D4-E587-4BA8-B6A5-A97CCA6AFFD3'
HTML_CHRC = 'D1A517F0-2499-46CA-9CCC-809BC1C966FA'
def advertise_beacon():
dongle = adapter.Adapter('/org/bluez/hci0')
advertiser0.service_UUIDs = ['FEAA']
advertiser0.service_data = {'FEAA': [0x10, 0x08, 0x0E, 70, 97,
116, 79, 110, 101]}
if not dongle.powered:
dongle.powered = True
ad_manager = advertisement.AdvertisingManager(dongle.path)
ad_manager.register_advertisement(advertiser0, {})
def build_fat_service():
html_string = """<html><head><style>
body { background-color: linen; }
h1 { color: maroon; margin-left: 40px; }
</style><title>FatBeacon Demo</title>
<meta charset='UTF-8'><meta name='description' content='FatBeacon Demo'/>
</head> <body> <h1>Fat Beacon</h1> <p>
A FatBeacon is a beacon that rather than advertising a URL
to load a web page from it actually hosts the web page on the
device and services it up from the BLE characteristic
</p> </body> </html>"""
html_ord = []
for char in html_string:
html_ord.append(ord(char))
app = localGATT.Application()
srv = localGATT.Service(1, FAT_SERVICE, True)
fat_html = localGATT.Characteristic(1,
HTML_CHRC,
srv,
html_ord,
False,
['read'])
10 Chapter 2. Examples
python-bluezero Documentation, Release 0.0.4
fat_html.service = srv.path
app.add_managed_object(srv)
app.add_managed_object(fat_html)
srv_mng = GATT.GattManager('/org/bluez/hci0')
srv_mng.register_application(app, {})
if __name__ == '__main__':
build_fat_service()
try:
tools.start_mainloop()
except KeyboardInterrupt:
tools.stop_mainloop()
ad_manager.unregister_advertisement(advertiser)
finally:
pass
2.1. Examples 11
python-bluezero Documentation, Release 0.0.4
12 Chapter 2. Examples
CHAPTER 3
Installing Bluez
Installing Bluez
Overview
Bluezero relies on the dbus interface of Bluez. This library requires the features provided by Bluez version 5.43 and
later. As this is as recent build, it is unlikely that the Linux version you have installed will have the correct version.
These instructions are intended to jump start the switching to a newer version of Bluez which will need to be built
from source.
The following packages are a super set of what is required. For some systems these may already be install or not
required:
If you are looking to contribute to the development of Bluezero then you will need:
13
python-bluezero Documentation, Release 0.0.4
wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.43.tar.xz
tar xf bluez-5.43.tar.xz
cd bluez-5.43
To configure run:
./configure --prefix=/usr \
--mandir=/usr/share/man \
--sysconfdir=/etc \
--localstatedir=/var \
--enable-experimental \
--enable-maintainer-mode
Note: On the Raspberry Pi 3 installing the latest version of BlueZ breaks the connection to the controller. See
Bluezero GitHub repository issue 30 on how to patch BlueZ to use with a Raspberry Pi 3
Some of the BlueZ DBus API functionality is still behind an experimental flag. This can be switch on by default in
the bluetooth.service file
Edit bluetooth.service file to add –experimental flag e.g:
The bluetoothd should now be the new version. To check the bluetoothd is running:
service bluetooth status
Much of what Bluezero is doing is using Bluetooth Low Energy. It has been discovered to get reliable connection to
Android phones it is best to put the controller into le only mode. This is done in the /etc/bluetooth/main.
conf file. Ensure that it contains the following:
ControllerMode = le
A peripheral application will be registered on the DBus using the bus name of ukBaz.bluezero. An example dbus
configuration file is provided and will need to be copied to the correct location:
sudo cp examples/ukBaz.bluezero.conf /etc/dbus-1/system.d/.
Kill the process (use ‘service bluetooth status’ to get the pid) the launch daemon with debug:
sudo /usr/libexec/bluetooth/bluetoothd -nEd |& tee ~/bluetoothd.log
/usr/libexec/bluetooth/bluetoothd -nEd
dbus-monitor --system
python-bluezero modules
python-bluezero Modules
Level 1
Eddystone
micro:bit
blinkt
Level 10
Broadcaster
Central
Level 100
Adapter
Device
Advertisement
Shared
17
python-bluezero Documentation, Release 0.0.4
Tools
Constants
bluezero.constants.ADAPTER_INTERFACE = ‘org.bluez.Adapter1’
BlueZ DBus adapter interface
bluezero.constants.BLUEZ_SERVICE_NAME = ‘org.bluez’
BlueZ DBus Service Name
bluezero.constants.DBUS_OM_IFACE = ‘org.freedesktop.DBus.ObjectManager’
The DBus Object Manager interface
bluezero.constants.DBUS_PROP_IFACE = ‘org.freedesktop.DBus.Properties’
DBus Properties interface
bluezero.constants.DEVICE_INTERFACE = ‘org.bluez.Device1’
BlueZ DBus device Interface
bluezero.constants.GATT_CHRC_IFACE = ‘org.bluez.GattCharacteristic1’
BlueZ DBus GATT Characteristic Interface
bluezero.constants.GATT_DESC_IFACE = ‘org.bluez.GattDescriptor1’
BlueZ DBus GATT Descriptor Interface
bluezero.constants.GATT_MANAGER_IFACE = ‘org.bluez.GattManager1’
BlueZ DBus GATT manager Interface
bluezero.constants.GATT_PROFILE_IFACE = ‘org.bluez.GattProfile1’
BlueZ DBus GATT Profile Interface
bluezero.constants.GATT_SERVICE_IFACE = ‘org.bluez.GattService1’
BlueZ DBus GATT Service Interface
bluezero.constants.LE_ADVERTISEMENT_IFACE = ‘org.bluez.LEAdvertisement1’
BlueZ DBus Advertisement Interface
bluezero.constants.LE_ADVERTISING_MANAGER_IFACE = ‘org.bluez.LEAdvertisingManager1’
BlueZ DBus Advertising Manager Interface
DBus Tools
b
bluezero.constants, 18
bluezero.tools, 18
21
python-bluezero Documentation, Release 0.0.4
A U
ADAPTER_INTERFACE (in module url_to_advert() (in module bluezero.tools), 18
bluezero.constants), 18
B
BLUEZ_SERVICE_NAME (in module
bluezero.constants), 18
bluezero.constants (module), 18
bluezero.tools (module), 18
bytes_to_xyz() (in module bluezero.tools), 18
D
DBUS_OM_IFACE (in module bluezero.constants), 18
DBUS_PROP_IFACE (in module bluezero.constants), 18
DEVICE_INTERFACE (in module bluezero.constants),
18
G
GATT_CHRC_IFACE (in module bluezero.constants), 18
GATT_DESC_IFACE (in module bluezero.constants), 18
GATT_MANAGER_IFACE (in module
bluezero.constants), 18
GATT_PROFILE_IFACE (in module
bluezero.constants), 18
GATT_SERVICE_IFACE (in module
bluezero.constants), 18
I
int_to_uint16() (in module bluezero.tools), 18
int_to_uint32() (in module bluezero.tools), 18
L
LE_ADVERTISEMENT_IFACE (in module
bluezero.constants), 18
LE_ADVERTISING_MANAGER_IFACE (in module
bluezero.constants), 19
S
sint16_to_int() (in module bluezero.tools), 18
23