src.bluetooth_sig.device.peripheral

Peripheral manager protocol for BLE GATT server adapters.

Defines an async abstract base class that peripheral adapter implementations (bless, bluez_peripheral, etc.) must inherit from to create BLE GATT servers that broadcast services and characteristics.

Adapters must provide async implementations of all abstract methods below.

Classes

Name

Description

PeripheralManagerProtocol

Abstract base class for BLE peripheral/GATT server implementations.

Module Contents

class src.bluetooth_sig.device.peripheral.PeripheralManagerProtocol(name: str)

Bases: abc.ABC

Abstract base class for BLE peripheral/GATT server implementations.

Deprecated since version 0.5.0: Scheduled for removal; see docs/source/explanation/limitations.md.

This protocol defines the interface for creating BLE peripherals that broadcast services and characteristics. Implementations wrap backend libraries like bless, bluez_peripheral, etc.

Uses a fluent builder pattern for advertisement configuration - call configuration methods before start() to customise advertising.

The workflow is: 1. Create peripheral manager with a device name 2. Configure advertising (optional): with_manufacturer_data(), with_tx_power(), etc. 3. Add services and characteristics (using CharacteristicDefinition) 4. Start advertising 5. Update characteristic values as needed 6. Stop when done

Example::
>>> from bluetooth_sig.gatt.characteristics import BatteryLevelCharacteristic
>>> from bluetooth_sig.gatt.services import BatteryService
>>> from bluetooth_sig.types.company import ManufacturerData
>>>
>>> # Create peripheral with fluent configuration
>>> peripheral = SomePeripheralManager("My Sensor")
>>> peripheral.with_tx_power(-10).with_connectable(True)
>>>
>>> # Define a service with battery level
>>> char = BatteryLevelCharacteristic()
>>> char_def = CharacteristicDefinition.from_characteristic(char, 85)
>>>
>>> service = ServiceDefinition(
...     uuid=BatteryService.get_class_uuid(),
...     characteristics=[char_def],
... )
>>>
>>> await peripheral.add_service(service)
>>> await peripheral.start()
>>>
>>> # Later, update the battery level
>>> await peripheral.update_characteristic("2A19", char.build_value(75))
async add_service(service: bluetooth_sig.types.peripheral_types.ServiceDefinition) None

Add a GATT service to the peripheral.

Services must be added before calling start(). Each service contains one or more characteristics that clients can interact with.

Parameters:

service – The service definition to add

Raises:

RuntimeError – If called after start()

get_characteristic_definition(char_uuid: str | bluetooth_sig.types.uuid.BluetoothUUID) bluetooth_sig.types.peripheral_types.CharacteristicDefinition | None

Get the characteristic definition by UUID.

Parameters:

char_uuid – UUID of the characteristic.

Returns:

CharacteristicDefinition if found, None otherwise.

abstractmethod get_characteristic_value(char_uuid: str | bluetooth_sig.types.uuid.BluetoothUUID) bytearray
Async:

Get the current value of a characteristic.

Parameters:

char_uuid – UUID of the characteristic

Returns:

The current encoded value

Raises:

KeyError – If characteristic UUID not found

set_read_callback(char_uuid: str | bluetooth_sig.types.uuid.BluetoothUUID, callback: collections.abc.Callable[[], bytearray]) None

Set a callback for dynamic read value generation.

When a client reads the characteristic, this callback will be invoked to generate the current value instead of returning the stored value.

Parameters:
  • char_uuid – UUID of the characteristic

  • callback – Function that returns the encoded value to serve

Raises:

KeyError – If characteristic UUID not found

set_write_callback(char_uuid: str | bluetooth_sig.types.uuid.BluetoothUUID, callback: collections.abc.Callable[[bytearray], None]) None

Set a callback for handling client writes.

When a client writes to the characteristic, this callback will be invoked with the written data.

Parameters:
  • char_uuid – UUID of the characteristic

  • callback – Function called with the written data

Raises:

KeyError – If characteristic UUID not found

abstractmethod start() None
Async:

Start advertising and accepting connections.

Backend implementations must: 1. Create the platform-specific GATT server 2. Register all services and characteristics from self._services 3. Configure advertisement data from self._manufacturer_data, etc. 4. Begin advertising

Raises:

RuntimeError – If no services have been added

abstractmethod stop() None
Async:

Stop advertising and disconnect all clients.

abstractmethod update_characteristic(char_uuid: str | bluetooth_sig.types.uuid.BluetoothUUID, value: bytearray, *, notify: bool = True) None
Async:

Update a characteristic’s value.

This sets the new value that will be returned when clients read the characteristic. If notify=True and the characteristic supports notifications, subscribed clients will be notified of the change.

Parameters:
  • char_uuid – UUID of the characteristic to update

  • value – New encoded value (use characteristic.build_value() to encode)

  • notify – If True, notify subscribed clients of the change

Raises:
with_connectable(connectable: bool) Self

Set whether the peripheral accepts connections.

Parameters:

connectable – True to accept connections (default), False for broadcast only.

Returns:

Self for method chaining.

Raises:

RuntimeError – If called after start().

with_discoverable(discoverable: bool) Self

Set whether the peripheral is discoverable.

Parameters:

discoverable – True to be discoverable (default), False otherwise.

Returns:

Self for method chaining.

Raises:

RuntimeError – If called after start().

with_manufacturer_data(manufacturer_data: bluetooth_sig.types.company.ManufacturerData) Self

Set manufacturer-specific advertising data.

Parameters:

manufacturer_data – ManufacturerData instance from the types module.

Returns:

Self for method chaining.

Raises:

RuntimeError – If called after start().

Example::
>>> from bluetooth_sig.types.company import ManufacturerData
>>> mfr = ManufacturerData.from_id_and_payload(0x004C, b"\x02\x15...")
>>> peripheral.with_manufacturer_data(mfr)
with_manufacturer_id(company_id: int | bluetooth_sig.types.company.CompanyIdentifier, payload: bytes) Self

Set manufacturer data from company ID and payload.

Parameters:
  • company_id – Bluetooth SIG company identifier (e.g., 0x004C for Apple) or CompanyIdentifier instance.

  • payload – Manufacturer-specific payload bytes.

Returns:

Self for method chaining.

Raises:

RuntimeError – If called after start().

Example::
>>> peripheral.with_manufacturer_id(0x004C, b"\x02\x15...")
with_service_data(service_uuid: bluetooth_sig.types.uuid.BluetoothUUID, data: bytes) Self

Add service data to advertisement.

Parameters:
  • service_uuid – BluetoothUUID of the service.

  • data – Service-specific data bytes.

Returns:

Self for method chaining.

Raises:

RuntimeError – If called after start().

Example::
>>> from bluetooth_sig.gatt.services import BatteryService
>>> peripheral.with_service_data(
...     BatteryService.get_class_uuid(),
...     b"\x50",  # 80% battery
... )
with_tx_power(power_dbm: int) Self

Set TX power level for advertising.

Parameters:

power_dbm – Transmission power in dBm (-127 to +127).

Returns:

Self for method chaining.

Raises:

RuntimeError – If called after start().

property connected_clients: int
Abstractmethod:

Get the number of currently connected clients.

Returns:

Number of connected BLE centrals

Raises:

NotImplementedError – If backend doesn’t track connections

property is_advertising: bool
Abstractmethod:

Check if the peripheral is currently advertising.

Returns:

True if advertising, False otherwise

property is_connectable_config: bool

Get the connectable configuration.

Returns:

True if peripheral is configured to accept connections.

property is_discoverable_config: bool

Get the discoverable configuration.

Returns:

True if peripheral is configured to be discoverable.

property manufacturer_data: bluetooth_sig.types.company.ManufacturerData | None

Get the configured manufacturer data.

Returns:

ManufacturerData if configured, None otherwise.

property name: str

Get the advertised device name.

Returns:

The device name as it appears to BLE scanners

property service_data: dict[bluetooth_sig.types.uuid.BluetoothUUID, bytes]

Get the configured service data.

Returns:

Dictionary mapping service UUIDs to data bytes.

property services: list[bluetooth_sig.types.peripheral_types.ServiceDefinition]

Get the list of registered services.

Returns:

List of ServiceDefinition objects added to this peripheral.

supports_advertising: ClassVar[bool] = True
property tx_power: int | None

Get the configured TX power level.

Returns:

TX power in dBm if configured, None otherwise.