bluezoo - BlueZ D-Bus API Mock
bluezoo is a Python library that provides an in-process mock for the BlueZ D-Bus API, primarily for testing Bluetooth-related applications. It intercepts D-Bus calls to 'org.bluez' on the system bus, allowing developers to simulate Bluetooth device behavior without requiring a physical Bluetooth adapter or a running BlueZ daemon. The current version is 1.0.2, and it appears to have a stable release cadence for bug fixes and minor improvements.
Common errors
-
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.ServiceUnknown: The name org.bluez was not provided by any .service files
cause This error occurs when `dbus-python` attempts to connect to the 'org.bluez' service, but either the real BlueZ daemon is not running, or `BlueZMock` is not active (e.g., outside its `with` block).fixEnsure your code that interacts with 'org.bluez' is executed within a `with BlueZMock() as mock:` block when testing, or verify the actual BlueZ daemon is running if you intend to use real hardware. -
AttributeError: 'BlueZMock' object has no attribute 'get_adapter_by_path' (or similar methods)
cause You are attempting to call D-Bus methods directly on the `BlueZMock` instance. `BlueZMock` intercepts D-Bus calls, but client code still interacts with the D-Bus service via `dbus-python` objects, not the `BlueZMock` object itself.fixInteract with the mocked BlueZ service using standard `dbus-python` patterns, e.g., `bus.get_object('org.bluez', adapter_path)` followed by `dbus.Interface(adapter_object, 'org.bluez.Adapter1')`. -
ImportError: cannot import name 'GLib' from 'gi.repository'
cause The `pygobject` library, which provides the `gi.repository.GLib` module necessary for `dbus-python`'s GLib main loop integration, is not installed in your environment.fixInstall `pygobject`: `pip install pygobject`.
Warnings
- gotcha bluezoo is a *mocking* library for the BlueZ D-Bus API, intended for testing. It does not provide real Bluetooth functionality. Do not use it as a replacement for a running BlueZ daemon in production or for actual Bluetooth communication.
- gotcha To effectively use bluezoo, your environment also needs `dbus-python` and `pygobject` (for `gi.repository.GLib`) installed. While not direct `bluezoo` dependencies, these are essential for client code to interact with the mocked D-Bus service in a realistic way.
- gotcha bluezoo only mocks the D-Bus interface of BlueZ. It does not mock direct kernel Bluetooth sockets (e.g., `bluetooth.socket`), HCI commands, or other low-level interactions. Code that bypasses D-Bus will not be affected by `BlueZMock`.
Install
-
pip install bluezoo
Imports
- BlueZMock
from bluezoo import BlueZMock
- generate_random_address
from bluezoo.util import generate_random_address
Quickstart
import dbus
import dbus.mainloop.glib
from bluezoo import BlueZMock
from bluezoo.util import generate_random_address
# NOTE: dbus-python and pygobject are required in the environment to use bluezoo effectively.
# Install them with: pip install dbus-python pygobject
# Make sure dbus-python uses the GLib main loop by default for this process.
# This is crucial for BlueZ D-Bus interactions.
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
# Use BlueZMock as a context manager to activate the mock D-Bus service.
with BlueZMock() as mock:
print("BlueZMock is active, intercepting BlueZ D-Bus calls.")
# 1. Add a mock Bluetooth adapter
adapter_path = '/org/bluez/hci0'
mock.add_adapter(adapter_path, name='MockAdapter', address=generate_random_address())
print(f"Mock adapter '{adapter_path}' added.")
# 2. Add a mock Bluetooth device associated with the adapter
device_address = generate_random_address()
device_path = f'{adapter_path}/dev_{device_address.replace(":", "_")}'
mock.add_device(
device_path,
adapter_path=adapter_path,
address=device_address,
name='MockDevice',
rssi=-60
)
print(f"Mock device '{device_address}' added to adapter '{adapter_path}'.")
# 3. Now, client code (using dbus-python) can interact with these mock objects.
# Get the system bus
bus = dbus.SystemBus()
# Get the D-Bus ObjectManager to discover objects
obj_manager = dbus.Interface(
bus.get_object('org.bluez', '/'),
'org.freedesktop.DBus.ObjectManager'
)
# Get all managed objects and check for our mock adapter and device
managed_objects = obj_manager.GetManagedObjects()
print("\nVerifying mock objects via D-Bus ObjectManager:")
found_adapter = False
found_device = False
for path, interfaces in managed_objects.items():
if path == adapter_path and 'org.bluez.Adapter1' in interfaces:
print(f" Found mock adapter at {path} with name: {interfaces['org.bluez.Adapter1']['Name']}")
found_adapter = True
if path == device_path and 'org.bluez.Device1' in interfaces:
print(f" Found mock device at {path} with address: {interfaces['org.bluez.Device1']['Address']}")
found_device = True
if not (found_adapter and found_device):
print(" Error: Mock adapter or device not found via D-Bus as expected!")
print("\nBlueZMock is inactive now (outside the 'with' block).")
print("D-Bus calls to 'org.bluez' would now target the real BlueZ daemon if running, or fail.")
# Optional: Demonstrate failure outside the mock context
try:
bus = dbus.SystemBus()
# This call would fail if no real BlueZ daemon is running
bus.get_object('org.bluez', '/')
except dbus.exceptions.DBusException as e:
print(f"Attempting to access BlueZ outside mock context resulted in expected error: {e}")