Bluetooth mesh blues
2019
Introduction to BlueZ mesh, via Python/asyncio
What is D-Bus
(baby don't hurt me)
Operating System
App
Kernel
User
Some syscalls require
privileged acess!
What is D-Bus
(baby don't hurt me)
Service
Service
Service
Operating System
App
App
App
API
API
API
Root
What is D-Bus
(baby don't hurt me)
Message bus
Service
Service
Service
Operating System
App
App
App
API
API
API
D-Bus API: BlueZ
Message bus
BlueZ
org.bluez.mesh
/org/bluez/mesh
/org/bluez/mesh/node<uuid>
org.bluez.mesh.Network1
org.bluez.mesh.Node1
org.bluez.mesh.Management1
D-Bus API: Application
Message bus
App
<unnamed>
/com/silvair/app
/com/silvair/app/element<n>
org.bluez.mesh.Application1
org.bluez.mesh.ProvisionAgent1
org.bluez.mesh.Element1
D-Bus API: Provisioning
BlueZ
App
Provisioner
Join "/com/silvair/app", <uuid>
JoinComplete <token>
Provisioning
Attach <token>
GetManagedObjects
Send ...
<configuration>
D-Bus API: Importing
BlueZ
App
Provisioner
ImportLocalNode ...
<token>
Attach <token>
GetManagedObjects
Send ...
<configuration>
Application Interface
BlueZ
App
Provisioner
class Application:
def __init__(self):
self.bus = ravel.system_bus(managed_objects=True)
self.path = "/com/silvair/app"
self.bus.register(self.path, interface=ApplicationInterface(self))
self.bus.object_added(self.path)
@ravel.interface(ravel.ITERFACE_SERVER, name='org.bluez.mesh.Application1')
class ApplicationInterface:
def __init__(self, application):
self.application = application
@ravel.method(name='JoinComplete',
in_signature='t', out_signature='')
def join_complete(self, token):
return self.application.join_complete(token)
# ...
Element Interface
BlueZ
App
Provisioner
class Element:
def __init__(self, application, index):
self.path = '%s/element%02d' % (application.path, index)
# ...
class Application:
def __init__(self):
# ...
self.element = Element(self, index=0)
self.bus.register(self.element.path, interface=ElementInterface(self.element)
self.bus.object_added(path)
@ravel.interface(ravel.ITERFACE_SERVER, name='org.bluez.mesh.Element1')
class ElementInterface:
def __init__(self, element):
self.element = element
@ravel.method(name='MessageReceived',
in_signature='qqbay', out_signature='')
def message_received(self, source, application_key, subscription, data):
return self.element.message_received(source, application_key,
subscription, bytes(data))
Talking to BlueZ
BlueZ
App
Provisioner
class Application:
def __init__(self):
self.mesh_service = self.bus['org.bluez.mesh']
self.token = ...
async def connect(self):
network_object = self.mesh_service['/org/bluez/mesh']
network_interface = await network_object \
.get_async_interface('org.bluez.mesh.Network1')
node_path, configuration = \
await network_interface.Attach(self.PATH, token)
node_object = self.mesh_service[node_path]
self.node_interface = await node_object \
.get_async_interface('org.bluez.mesh.Node1')
Talking to BlueZ: sending
BlueZ
App
Provisioner
class Application:
async def send(self):
await self.node_interface.Send(self.element.path,
destination=0x0042,
application_key=0,
bytes.fromhex('800501'))
Talking to BlueZ: receiving
BlueZ
App
Provisioner
class Element:
def message_received(self, src, app_key, sub, msg):
self.application.message_received(self, src, app_key, sub, msg)
class Application:
def __init__(self):
self.message_callbacks = defaultdict(set)
def message_received(self, element, src, app_key, sub, msg):
opcode, params = parse(msg)
for cb in self.message_callbacks(opcode):
cb(element, src, app_key, sub, params)
Talking to BlueZ: receiving
BlueZ
App
Provisioner
class Application:
async def attention(self):
status = asyncio.Future()
def message_received(element, src, app_key, sub, params):
if element.path != self.element.path or src != 0x0042 or app_key != 0:
return
status.set_result(params)
opcode = 0x8007
self.message_callbacks[].add(message_received)
await self.node_interface.Send(self.element.path,
destination=0x0042,
application_key=0,
bytes.fromhex('800501'))
params = await status
homersoft/bluez-tests
AKA pymeshd
Thank you
Questions?
Bluetooth mesh blues @ Silvair
By Michał Lowas-Rzechonek
Bluetooth mesh blues @ Silvair
Introduction to BlueZ mesh, via Python/asyncio
- 822