Import Patterns

This guide shows you how to import the parts of bluetooth-sig you need for different tasks.

Quick Reference

Import the primary API for most tasks:

from bluetooth_sig import BluetoothSIGTranslator, Device

For Device usage, you also need a connection manager:

from examples.connection_managers.bleak_retry import (
    BleakRetryClientManager,
)

Import from submodules when you need specific features:

from bluetooth_sig.advertising import AdvertisingPDUParser
from bluetooth_sig.gatt.characteristics import BatteryLevelCharacteristic

Choosing an Import Path

You pay for what you import. The library loads individual characteristic and service implementations on first use, so you can keep startup lean when you only need parsing.

Start with the top-level API unless you have a reason not to:

from bluetooth_sig import BluetoothSIGTranslator

Use a submodule import when you need a specific feature (advertising, a named characteristic class, or the device layer):

from bluetooth_sig.advertising import AdvertisingPDUParser
from bluetooth_sig.gatt.characteristics import BatteryLevelCharacteristic
from bluetooth_sig import Device

If you integrate inside an async host (for example Home Assistant) and want to avoid blocking I/O on the first parse, see Performance Tuning for how to call :func:~bluetooth_sig.utils.prewarm.prewarm_registries during setup.

Named characteristic imports still work as before. Accessing BatteryLevelCharacteristic for the first time loads only that module, not the full characteristic catalogue.

How to Import for Common Tasks

Task: Parse characteristic data (type-safe)

Import the characteristic class directly for full type inference:

from bluetooth_sig.gatt.characteristics import BatteryLevelCharacteristic

battery = BatteryLevelCharacteristic()
level = battery.parse_value(bytearray([85]))  # IDE knows: int
encoded = battery.build_value(85)  # Encode back to bytes

Task: Parse unknown characteristics (dynamic)

Use the Translator when scanning unknown devices:

from bluetooth_sig import BluetoothSIGTranslator

translator = BluetoothSIGTranslator()

# UUID and data from device discovery (replace with actual BLE reads)
uuid = "2A19"  # Battery Level
raw_data = bytearray([75])

value = translator.parse_characteristic(uuid, raw_data)
info = translator.get_characteristic_info_by_uuid(uuid)
print(f"{info.name}: {value}")  # Battery Level: 75

Task: Parse advertising packets

Import from the advertising module:

from bluetooth_sig.advertising import AdvertisingPDUParser

parser = AdvertisingPDUParser()
raw_adv_bytes = bytearray([0x02, 0x01, 0x06])  # Example advertising data
adv_data = parser.parse_advertising_data(raw_adv_bytes)

Task: Work with multiple characteristics (type-safe)

Import characteristic classes for full IDE support:

from bluetooth_sig.gatt.characteristics import (
    BatteryLevelCharacteristic,
    BodySensorLocationCharacteristic,
    HeartRateMeasurementCharacteristic,
)

# Example data (replace with actual BLE reads)
hr_bytes = bytearray([0x00, 75])  # Heart rate 75 bpm
loc_bytes = bytearray([0x01])  # Chest location
bat_bytes = bytearray([85])  # 85% battery

hr_char = HeartRateMeasurementCharacteristic()
sensor_char = BodySensorLocationCharacteristic()
battery_char = BatteryLevelCharacteristic()

# All have full type inference
hr_data = hr_char.parse_value(hr_bytes)  # HeartRateData
location = sensor_char.parse_value(loc_bytes)  # int
level = battery_char.parse_value(bat_bytes)  # int

Task: Add type hints to your code

Import the data types you need. The library returns parsed values directly, so type hints use the actual value types:

from bluetooth_sig.gatt.characteristics import (
    HeartRateMeasurementCharacteristic,
)

# Example data (replace with actual BLE reads)
raw_bytes = bytearray([0x00, 72])  # Heart rate 72 bpm

# Type annotations use the characteristic's return type
hr_char = HeartRateMeasurementCharacteristic()
hr_data = hr_char.parse_value(raw_bytes)  # IDE knows: HeartRateData

# For dynamic parsing, return type is Any
from bluetooth_sig import BluetoothSIGTranslator

translator = BluetoothSIGTranslator()
uuid = "2A37"
data = bytearray([0x00, 72])
value = translator.parse_characteristic(uuid, data)  # Returns Any

Task: Use the Device abstraction (type-safe)

Import Device with characteristic classes:

# SKIP: Requires async context and BLE hardware
from bluetooth_sig import Device
from bluetooth_sig.gatt.characteristics import BatteryLevelCharacteristic
from examples.connection_managers.bleak_retry import (
    BleakRetryClientManager,
)

connection_manager = BleakRetryClientManager("AA:BB:CC:DD:EE:FF")
device = Device(connection_manager)

# Type-safe read - IDE knows level is int
battery = BatteryLevelCharacteristic()
level = await device.read_characteristic(battery)

Task: Use the Device abstraction (dynamic)

Import Device with Translator for unknown devices:

# SKIP: Requires async context and BLE hardware
from bluetooth_sig import BluetoothSIGTranslator, Device
from examples.connection_managers.bleak_retry import (
    BleakRetryClientManager,
)

translator = BluetoothSIGTranslator()
connection_manager = BleakRetryClientManager("AA:BB:CC:DD:EE:FF")
device = Device(connection_manager, translator)

# Dynamic read - returns CharacteristicData with Any value
uuid_from_discovery = "2A19"  # Example: Battery Level from service discovery
result = await device.read_characteristic_by_uuid(uuid_from_discovery)

Task: Work with registries programmatically

Import from the registry module:

from bluetooth_sig import BluetoothSIGTranslator

translator = BluetoothSIGTranslator()
char_uuid = translator.get_characteristic_uuid_by_name("Battery Level")

Task: Create a custom characteristic

Import base classes:

from bluetooth_sig.gatt.characteristics.base import BaseCharacteristic
from bluetooth_sig.types.data_types import CharacteristicInfo


class MyCustomCharacteristic(BaseCharacteristic):
    _info = CharacteristicInfo(
        uuid="12345678-1234-5678-1234-56789abcdef0",
        name="My Custom Characteristic",
    )

What’s Available at Each Level

Top level (from bluetooth_sig import X)

The primary API and essential types. Importing here loads the translator and shared infrastructure, but not every characteristic implementation:

  • BluetoothSIGTranslator - Main parsing API

  • AsyncParsingSession - Async context manager

  • Device - High-level device abstraction

  • CharacteristicData - Return type for parsed data

  • CharacteristicInfo - Characteristic metadata

  • ServiceInfo - Service metadata

  • ValidationResult - Validation results

  • SIGInfo - SIG standard info

  • prewarm_registries - Optional eager registry loading for production hosts

  • __version__ - Package version

Submodules (explicit imports)

Import from specific modules as needed:

Advertising: bluetooth_sig.advertising

  • AdvertisingPDUParser

  • AdvertisingDataInterpreter

  • AdvertisingInterpreterRegistry

Characteristics: bluetooth_sig.gatt.characteristics

  • All characteristic classes (for example BatteryLevelCharacteristic) — loaded on first access

Services: bluetooth_sig.gatt.services

  • All service classes (e.g., BatteryService)

Registries: bluetooth_sig.registry

  • UUID resolution utilities

  • YAML cross-reference system

Base classes (for extending): bluetooth_sig.gatt.characteristics.base

  • BaseCharacteristic

  • BaseGattService

Connection managers (from examples): examples.connection_managers

  • BleakRetryClientManager - Bleak-based async manager with retry logic

  • SimplePyBLEConnectionManager - SimplePyBLE synchronous adapter

  • BluePyConnectionManager - BluePy adapter

These implement ConnectionManagerProtocol and are required for Device usage.

Troubleshooting Imports

Problem: ImportError: cannot import name 'AdvertisingPDUParser'

Solution: Use explicit submodule import:

from bluetooth_sig.advertising import AdvertisingPDUParser

Problem: Need to find where a class lives

Solution: Check the module structure:

  • Advertising → bluetooth_sig.advertising

  • Characteristics → bluetooth_sig.gatt.characteristics

  • Services → bluetooth_sig.gatt.services

  • Device → bluetooth_sig.device

  • Registries → bluetooth_sig.registry

Best Practices

  1. Start simple: Begin with BluetoothSIGTranslator from the top level

  2. Import what you need: Only import from submodules when necessary

  3. No wildcards: Avoid from bluetooth_sig import *

  4. Group logically: Keep standard library, third-party, and bluetooth-sig imports separated

  5. Be explicit: Clear imports make code easier to understand and maintain

Best Practices

  1. Start with the primary API: Always begin with BluetoothSIGTranslator at the top level

  2. Import what you use: Only import from submodules when you need specific features

  3. Use type hints: Import data types (CharacteristicInfo, etc.) for better type checking

  4. Avoid wildcards: Never use from bluetooth_sig import * - be explicit about what you’re importing

  5. Group imports logically:

# Standard library
import asyncio

# Third-party
from bleak import BleakClient

# bluetooth-sig primary API
from bluetooth_sig import BluetoothSIGTranslator, CharacteristicInfo

# bluetooth-sig submodules
from bluetooth_sig.advertising import AdvertisingPDUParser
from bluetooth_sig.gatt.characteristics import (
    HeartRateMeasurementCharacteristic,
)

Related Documentation