Skip to content

Core API Reference

The core API provides the main entry point for using the Bluetooth SIG Standards Library.

Pure Bluetooth SIG standards translator for characteristic and service interpretation.

This class provides the primary API surface for Bluetooth SIG standards translation, covering characteristic parsing, service discovery, UUID resolution, and registry management.

Key features: - Parse raw BLE characteristic data using Bluetooth SIG specifications - Resolve UUIDs to CharacteristicInfo and ServiceInfo - Create BaseGattService instances from service UUIDs - Access comprehensive registry of supported characteristics and services

Note: This class intentionally has >20 public methods as it serves as the primary API surface for Bluetooth SIG standards translation. The methods are organized by functionality and reducing them would harm API clarity.

Initialize the SIG translator.

Source code in src/bluetooth_sig/core/translator.py
def __init__(self) -> None:
    """Initialize the SIG translator."""
    self._services: dict[str, BaseGattService] = {}

discovered_services property

discovered_services: list[BaseGattService]

Get list of discovered service instances.

Returns:

Type Description
list[BaseGattService]

List of discovered service instances

__str__

__str__() -> str

Return string representation of the translator.

Source code in src/bluetooth_sig/core/translator.py
def __str__(self) -> str:
    """Return string representation of the translator."""
    return "BluetoothSIGTranslator(pure SIG standards)"

clear_services

clear_services() -> None

Clear all discovered services.

Source code in src/bluetooth_sig/core/translator.py
def clear_services(self) -> None:
    """Clear all discovered services."""
    self._services.clear()

get_characteristic_info_by_name

get_characteristic_info_by_name(name: CharacteristicName) -> CharacteristicInfo | None

Get characteristic info by enum name.

Parameters:

Name Type Description Default
name CharacteristicName

CharacteristicName enum

required

Returns:

Type Description
CharacteristicInfo | None

CharacteristicInfo if found, None otherwise

Source code in src/bluetooth_sig/core/translator.py
def get_characteristic_info_by_name(self, name: CharacteristicName) -> CharacteristicInfo | None:
    """Get characteristic info by enum name.

    Args:
        name: CharacteristicName enum

    Returns:
        CharacteristicInfo if found, None otherwise

    """
    char_class = CharacteristicRegistry.get_characteristic_class(name)
    if char_class:
        return char_class.get_configured_info()
    return None

get_characteristic_info_by_uuid

get_characteristic_info_by_uuid(uuid: str) -> CharacteristicInfo | None

Get information about a characteristic by UUID.

Retrieve metadata for a Bluetooth characteristic using its UUID. This includes the characteristic's name, description, value type, unit, and properties.

Parameters:

Name Type Description Default
uuid str

The characteristic UUID (16-bit short form or full 128-bit)

required

Returns:

Type Description
CharacteristicInfo | None

CharacteristicInfo with metadata or None if not found

Example

Get battery level characteristic info:

from bluetooth_sig import BluetoothSIGTranslator

translator = BluetoothSIGTranslator()
info = translator.get_characteristic_info_by_uuid("2A19")
if info:
    print(f"Name: {info.name}")  # Name: Battery Level
Source code in src/bluetooth_sig/core/translator.py
def get_characteristic_info_by_uuid(self, uuid: str) -> CharacteristicInfo | None:
    """Get information about a characteristic by UUID.

    Retrieve metadata for a Bluetooth characteristic using its UUID. This includes
    the characteristic's name, description, value type, unit, and properties.

    Args:
        uuid: The characteristic UUID (16-bit short form or full 128-bit)

    Returns:
        [CharacteristicInfo][bluetooth_sig.CharacteristicInfo] with metadata or None if not found

    Example:
        Get battery level characteristic info:

        ```python
        from bluetooth_sig import BluetoothSIGTranslator

        translator = BluetoothSIGTranslator()
        info = translator.get_characteristic_info_by_uuid("2A19")
        if info:
            print(f"Name: {info.name}")  # Name: Battery Level
        ```

    """
    try:
        bt_uuid = BluetoothUUID(uuid)
    except ValueError:
        return None

    char_class = CharacteristicRegistry.get_characteristic_class_by_uuid(bt_uuid)
    if not char_class:
        return None

    # Create temporary instance to get metadata (no parameters needed for auto-resolution)
    try:
        temp_char = char_class()
        return temp_char.info
    except Exception:  # pylint: disable=broad-exception-caught
        return None

get_characteristic_uuid_by_name

get_characteristic_uuid_by_name(name: CharacteristicName) -> BluetoothUUID | None

Get the UUID for a characteristic name enum.

Parameters:

Name Type Description Default
name CharacteristicName

CharacteristicName enum

required

Returns:

Type Description
BluetoothUUID | None

Characteristic UUID or None if not found

Source code in src/bluetooth_sig/core/translator.py
def get_characteristic_uuid_by_name(self, name: CharacteristicName) -> BluetoothUUID | None:
    """Get the UUID for a characteristic name enum.

    Args:
        name: CharacteristicName enum

    Returns:
        Characteristic UUID or None if not found

    """
    info = self.get_characteristic_info_by_name(name)
    return info.uuid if info else None

get_characteristics_info_by_uuids

get_characteristics_info_by_uuids(uuids: list[str]) -> dict[str, CharacteristicInfo | None]

Get information about multiple characteristics by UUID.

Parameters:

Name Type Description Default
uuids list[str]

List of characteristic UUIDs

required

Returns:

Type Description
dict[str, CharacteristicInfo | None]

Dictionary mapping UUIDs to CharacteristicInfo

dict[str, CharacteristicInfo | None]

(or None if not found)

Source code in src/bluetooth_sig/core/translator.py
def get_characteristics_info_by_uuids(self, uuids: list[str]) -> dict[str, CharacteristicInfo | None]:
    """Get information about multiple characteristics by UUID.

    Args:
        uuids: List of characteristic UUIDs

    Returns:
        Dictionary mapping UUIDs to CharacteristicInfo
        (or None if not found)

    """
    results: dict[str, CharacteristicInfo | None] = {}
    for uuid in uuids:
        results[uuid] = self.get_characteristic_info_by_uuid(uuid)
    return results

get_service_by_uuid

get_service_by_uuid(uuid: str) -> BaseGattService | None

Get a service instance by UUID.

Parameters:

Name Type Description Default
uuid str

The service UUID

required

Returns:

Type Description
BaseGattService | None

Service instance if found, None otherwise

Source code in src/bluetooth_sig/core/translator.py
def get_service_by_uuid(self, uuid: str) -> BaseGattService | None:
    """Get a service instance by UUID.

    Args:
        uuid: The service UUID

    Returns:
        Service instance if found, None otherwise

    """
    return self._services.get(uuid)

get_service_characteristics

get_service_characteristics(service_uuid: str) -> list[str]

Get the characteristic UUIDs associated with a service.

Parameters:

Name Type Description Default
service_uuid str

The service UUID

required

Returns:

Type Description
list[str]

List of characteristic UUIDs for this service

Source code in src/bluetooth_sig/core/translator.py
def get_service_characteristics(self, service_uuid: str) -> list[str]:  # pylint: disable=too-many-return-statements
    """Get the characteristic UUIDs associated with a service.

    Args:
        service_uuid: The service UUID

    Returns:
        List of characteristic UUIDs for this service

    """
    service_class = GattServiceRegistry.get_service_class_by_uuid(BluetoothUUID(service_uuid))
    if not service_class:
        return []

    try:
        temp_service = service_class()
        required_chars = temp_service.get_required_characteristics()
        return [str(k) for k in required_chars]
    except Exception:  # pylint: disable=broad-exception-caught
        return []

get_service_info_by_name

get_service_info_by_name(name: str) -> ServiceInfo | None

Get service info by name instead of UUID.

Parameters:

Name Type Description Default
name str

Service name

required

Returns:

Type Description
ServiceInfo | None

ServiceInfo if found, None otherwise

Source code in src/bluetooth_sig/core/translator.py
def get_service_info_by_name(self, name: str) -> ServiceInfo | None:
    """Get service info by name instead of UUID.

    Args:
        name: Service name

    Returns:
        ServiceInfo if found, None otherwise

    """
    # Use UUID registry for name-based lookup
    try:
        uuid_info = uuid_registry.get_service_info(name)
        if uuid_info:
            return ServiceInfo(uuid=uuid_info.uuid, name=uuid_info.name, characteristics=[])
    except Exception:  # pylint: disable=broad-exception-caught
        pass

    return None

get_service_info_by_uuid

get_service_info_by_uuid(uuid: str) -> ServiceInfo | None

Get information about a service by UUID.

Parameters:

Name Type Description Default
uuid str

The service UUID

required

Returns:

Type Description
ServiceInfo | None

ServiceInfo with metadata or None if not found

Source code in src/bluetooth_sig/core/translator.py
def get_service_info_by_uuid(self, uuid: str) -> ServiceInfo | None:
    """Get information about a service by UUID.

    Args:
        uuid: The service UUID

    Returns:
        ServiceInfo with metadata or None if not found

    """
    service_class = GattServiceRegistry.get_service_class_by_uuid(BluetoothUUID(uuid))
    if not service_class:
        return None

    try:
        temp_service = service_class()
        # Convert characteristics dict to list of CharacteristicInfo
        char_infos: list[CharacteristicInfo] = []
        for _, char_instance in temp_service.characteristics.items():
            # Use public info property
            char_infos.append(char_instance.info)
        return ServiceInfo(
            uuid=temp_service.uuid,
            name=temp_service.name,
            characteristics=char_infos,
        )
    except Exception:  # pylint: disable=broad-exception-caught
        return None

get_service_uuid_by_name

get_service_uuid_by_name(name: str | ServiceName) -> BluetoothUUID | None

Get the UUID for a service name or enum.

Parameters:

Name Type Description Default
name str | ServiceName

Service name or enum

required

Returns:

Type Description
BluetoothUUID | None

Service UUID or None if not found

Source code in src/bluetooth_sig/core/translator.py
def get_service_uuid_by_name(self, name: str | ServiceName) -> BluetoothUUID | None:
    """Get the UUID for a service name or enum.

    Args:
        name: Service name or enum

    Returns:
        Service UUID or None if not found

    """
    info = self.get_service_info_by_name(str(name))
    return info.uuid if info else None

get_sig_info_by_name

get_sig_info_by_name(name: str) -> SIGInfo | None

Get Bluetooth SIG information for a characteristic or service by name.

Parameters:

Name Type Description Default
name str

Characteristic or service name

required

Returns:

Type Description
SIGInfo | None

CharacteristicInfo or ServiceInfo if found, None otherwise

Source code in src/bluetooth_sig/core/translator.py
def get_sig_info_by_name(self, name: str) -> SIGInfo | None:
    """Get Bluetooth SIG information for a characteristic or service by name.

    Args:
        name: Characteristic or service name

    Returns:
        CharacteristicInfo or ServiceInfo if found, None otherwise

    """
    # Use the UUID registry for name-based lookups (string inputs).
    try:
        char_info = uuid_registry.get_characteristic_info(name)
        if char_info:
            # Build CharacteristicInfo from registry data
            value_type = ValueType.UNKNOWN
            if char_info.value_type:
                try:
                    value_type = ValueType(char_info.value_type)
                except (ValueError, KeyError):
                    value_type = ValueType.UNKNOWN
            return CharacteristicInfo(
                uuid=char_info.uuid,
                name=char_info.name,
                value_type=value_type,
                unit=char_info.unit or "",
            )
    except Exception:  # pylint: disable=broad-exception-caught
        pass

    # Try service
    service_info = self.get_service_info_by_name(name)
    if service_info:
        return service_info

    return None

get_sig_info_by_uuid

get_sig_info_by_uuid(uuid: str) -> SIGInfo | None

Get Bluetooth SIG information for a UUID.

Parameters:

Name Type Description Default
uuid str

UUID string (with or without dashes)

required

Returns:

Type Description
SIGInfo | None

CharacteristicInfo or ServiceInfo if found, None otherwise

Source code in src/bluetooth_sig/core/translator.py
def get_sig_info_by_uuid(self, uuid: str) -> SIGInfo | None:
    """Get Bluetooth SIG information for a UUID.

    Args:
        uuid: UUID string (with or without dashes)

    Returns:
        CharacteristicInfo or ServiceInfo if found, None otherwise

    """
    # Try characteristic first
    char_info = self.get_characteristic_info_by_uuid(uuid)
    if char_info:
        return char_info

    # Try service
    service_info = self.get_service_info_by_uuid(uuid)
    if service_info:
        return service_info

    return None

list_supported_characteristics

list_supported_characteristics() -> dict[str, str]

List all supported characteristics with their names and UUIDs.

Returns:

Type Description
dict[str, str]

Dictionary mapping characteristic names to UUIDs

Source code in src/bluetooth_sig/core/translator.py
def list_supported_characteristics(self) -> dict[str, str]:
    """List all supported characteristics with their names and UUIDs.

    Returns:
        Dictionary mapping characteristic names to UUIDs

    """
    result: dict[str, str] = {}
    for name, char_class in CharacteristicRegistry.get_all_characteristics().items():
        # Try to get configured_info from class using public accessor
        configured_info = char_class.get_configured_info()
        if configured_info:
            # Convert CharacteristicName enum to string for dict key
            name_str = name.value if hasattr(name, "value") else str(name)
            result[name_str] = str(configured_info.uuid)
    return result

list_supported_services

list_supported_services() -> dict[str, str]

List all supported services with their names and UUIDs.

Returns:

Type Description
dict[str, str]

Dictionary mapping service names to UUIDs

Source code in src/bluetooth_sig/core/translator.py
def list_supported_services(self) -> dict[str, str]:
    """List all supported services with their names and UUIDs.

    Returns:
        Dictionary mapping service names to UUIDs

    """
    result: dict[str, str] = {}
    for service_class in GattServiceRegistry.get_all_services():
        try:
            temp_service = service_class()
            service_name = getattr(temp_service, "_service_name", service_class.__name__)
            result[service_name] = str(temp_service.uuid)
        except Exception:  # pylint: disable=broad-exception-caught
            continue
    return result

parse_characteristic

parse_characteristic(uuid: str, raw_data: bytes, ctx: CharacteristicContext | None = None, descriptor_data: dict[str, bytes] | None = None) -> CharacteristicData

Parse a characteristic's raw data using Bluetooth SIG standards.

This method takes raw BLE characteristic data and converts it to structured, type-safe Python objects using official Bluetooth SIG specifications.

Parameters:

Name Type Description Default
uuid str

The characteristic UUID (with or without dashes)

required
raw_data bytes

Raw bytes from the characteristic

required
ctx CharacteristicContext | None

Optional CharacteristicContext providing device-level info and previously-parsed characteristics to the parser.

None
properties

Optional set of characteristic properties (unused, kept for protocol compatibility)

required
descriptor_data dict[str, bytes] | None

Optional dictionary mapping descriptor UUIDs to their raw data

None

Returns:

Type Description
CharacteristicData

CharacteristicData with parsed value and metadata

Example

Parse battery level data:

from bluetooth_sig import BluetoothSIGTranslator

translator = BluetoothSIGTranslator()
result = translator.parse_characteristic("2A19", b"\\x64")
print(f"Battery: {result.value}%")  # Battery: 100%
Source code in src/bluetooth_sig/core/translator.py
def parse_characteristic(
    self,
    uuid: str,
    raw_data: bytes,
    ctx: CharacteristicContext | None = None,
    descriptor_data: dict[str, bytes] | None = None,
) -> CharacteristicData:
    r"""Parse a characteristic's raw data using Bluetooth SIG standards.

    This method takes raw BLE characteristic data and converts it to structured,
    type-safe Python objects using official Bluetooth SIG specifications.

    Args:
        uuid: The characteristic UUID (with or without dashes)
        raw_data: Raw bytes from the characteristic
        ctx: Optional CharacteristicContext providing device-level info
            and previously-parsed characteristics to the parser.
        properties: Optional set of characteristic properties (unused, kept for protocol compatibility)
        descriptor_data: Optional dictionary mapping descriptor UUIDs to their raw data

    Returns:
        [CharacteristicData][bluetooth_sig.types.CharacteristicData] with parsed value and metadata

    Example:
        Parse battery level data:

        ```python
        from bluetooth_sig import BluetoothSIGTranslator

        translator = BluetoothSIGTranslator()
        result = translator.parse_characteristic("2A19", b"\\x64")
        print(f"Battery: {result.value}%")  # Battery: 100%
        ```

    """
    logger.debug("Parsing characteristic UUID=%s, data_len=%d", uuid, len(raw_data))

    # Create characteristic instance for parsing
    characteristic = CharacteristicRegistry.create_characteristic(uuid)

    if characteristic:
        logger.debug("Found parser for UUID=%s: %s", uuid, type(characteristic).__name__)
        # Use the parse_value method; pass context when provided.
        result = characteristic.parse_value(raw_data, ctx)

        # Attach context if available and result doesn't already have it
        if ctx is not None:
            result.source_context = ctx

        if result.parse_success:
            logger.debug("Successfully parsed %s: %s", result.name, result.value)
        else:
            logger.warning("Parse failed for %s: %s", result.name, result.error_message)

    else:
        # No parser found, return fallback result
        logger.info("No parser available for UUID=%s", uuid)
        fallback_info = CharacteristicInfo(
            uuid=BluetoothUUID(uuid),
            name="Unknown",
            description="",
            value_type=ValueType.UNKNOWN,
            unit="",
            properties=[],
        )
        result = CharacteristicData(
            info=fallback_info,
            value=raw_data,
            raw_data=raw_data,
            parse_success=False,
            error_message="No parser available for this characteristic UUID",
            descriptors={},  # No descriptors for unknown characteristics
        )

    # Handle descriptors if provided
    if descriptor_data:
        parsed_descriptors: dict[str, DescriptorData] = {}
        for desc_uuid, desc_raw_data in descriptor_data.items():
            logger.debug("Parsing descriptor %s for characteristic %s", desc_uuid, uuid)
            descriptor = DescriptorRegistry.create_descriptor(desc_uuid)
            if descriptor:
                desc_result = descriptor.parse_value(desc_raw_data)
                if desc_result.parse_success:
                    logger.debug("Successfully parsed descriptor %s: %s", desc_uuid, desc_result.value)
                else:
                    logger.warning("Descriptor parse failed for %s: %s", desc_uuid, desc_result.error_message)
                parsed_descriptors[desc_uuid] = desc_result
            else:
                logger.info("No parser available for descriptor UUID=%s", desc_uuid)
                # Create fallback descriptor data
                desc_fallback_info = DescriptorInfo(
                    uuid=BluetoothUUID(desc_uuid),
                    name="Unknown Descriptor",
                    description="",
                    has_structured_data=False,
                    data_format="bytes",
                )
                parsed_descriptors[desc_uuid] = DescriptorData(
                    info=desc_fallback_info,
                    value=desc_raw_data,
                    raw_data=desc_raw_data,
                    parse_success=False,
                    error_message="No parser available for this descriptor UUID",
                )

        # Update result with parsed descriptors
        result.descriptors = parsed_descriptors

    return result

parse_characteristics

parse_characteristics(char_data: dict[str, bytes], descriptor_data: dict[str, dict[str, bytes]] | None = None, ctx: CharacteristicContext | None = None) -> dict[str, CharacteristicData]

Parse multiple characteristics at once with dependency-aware ordering.

This method automatically handles multi-characteristic dependencies by parsing independent characteristics first, then parsing characteristics that depend on them. The parsing order is determined by the required_dependencies and optional_dependencies attributes declared on characteristic classes.

Required dependencies MUST be present and successfully parsed; missing required dependencies result in parse failure with MissingDependencyError. Optional dependencies enrich parsing when available but are not mandatory.

Parameters:

Name Type Description Default
char_data dict[str, bytes]

Dictionary mapping UUIDs to raw data bytes

required
descriptor_data dict[str, dict[str, bytes]] | None

Optional nested dictionary mapping characteristic UUIDs to dictionaries of descriptor UUIDs to raw descriptor data

None
ctx CharacteristicContext | None

Optional CharacteristicContext used as the starting device-level context for each parsed characteristic.

None

Returns:

Type Description
dict[str, CharacteristicData]

Dictionary mapping UUIDs to CharacteristicData results

dict[str, CharacteristicData]

with parsed descriptors included when descriptor_data is provided

Raises:

Type Description
ValueError

If circular dependencies are detected

Example

Parse multiple environmental characteristics:

from bluetooth_sig import BluetoothSIGTranslator

translator = BluetoothSIGTranslator()
data = {
    "2A6E": b"\\x0A\\x00",  # Temperature
    "2A6F": b"\\x32\\x00",  # Humidity
}
results = translator.parse_characteristics(data)
for uuid, result in results.items():
    print(f"{uuid}: {result.value}")
Source code in src/bluetooth_sig/core/translator.py
def parse_characteristics(
    self,
    char_data: dict[str, bytes],
    descriptor_data: dict[str, dict[str, bytes]] | None = None,
    ctx: CharacteristicContext | None = None,
) -> dict[str, CharacteristicData]:
    r"""Parse multiple characteristics at once with dependency-aware ordering.

    This method automatically handles multi-characteristic dependencies by parsing
    independent characteristics first, then parsing characteristics that depend on them.
    The parsing order is determined by the `required_dependencies` and `optional_dependencies`
    attributes declared on characteristic classes.

    Required dependencies MUST be present and successfully parsed; missing required
    dependencies result in parse failure with MissingDependencyError. Optional dependencies
    enrich parsing when available but are not mandatory.

    Args:
        char_data: Dictionary mapping UUIDs to raw data bytes
        descriptor_data: Optional nested dictionary mapping characteristic UUIDs to
            dictionaries of descriptor UUIDs to raw descriptor data
        ctx: Optional CharacteristicContext used as the starting
            device-level context for each parsed characteristic.

    Returns:
        Dictionary mapping UUIDs to [CharacteristicData][bluetooth_sig.types.CharacteristicData] results
        with parsed descriptors included when descriptor_data is provided

    Raises:
        ValueError: If circular dependencies are detected

    Example:
        Parse multiple environmental characteristics:

        ```python
        from bluetooth_sig import BluetoothSIGTranslator

        translator = BluetoothSIGTranslator()
        data = {
            "2A6E": b"\\x0A\\x00",  # Temperature
            "2A6F": b"\\x32\\x00",  # Humidity
        }
        results = translator.parse_characteristics(data)
        for uuid, result in results.items():
            print(f"{uuid}: {result.value}")
        ```

    """
    return self._parse_characteristics_batch(char_data, descriptor_data, ctx)

process_services

process_services(services: dict[str, dict[str, CharacteristicDataDict]]) -> None

Process discovered services and their characteristics.

Parameters:

Name Type Description Default
services dict[str, dict[str, CharacteristicDataDict]]

Dictionary of service UUIDs to their characteristics

required
Source code in src/bluetooth_sig/core/translator.py
def process_services(self, services: dict[str, dict[str, CharacteristicDataDict]]) -> None:
    """Process discovered services and their characteristics.

    Args:
        services: Dictionary of service UUIDs to their characteristics

    """
    for uuid_str, service_data in services.items():
        uuid = BluetoothUUID(uuid_str)
        # Convert dict[str, dict] to ServiceDiscoveryData
        characteristics: dict[BluetoothUUID, CharacteristicInfo] = {}
        for char_uuid_str, char_data in service_data.get("characteristics", {}).items():
            char_uuid = BluetoothUUID(char_uuid_str)
            # Create CharacteristicInfo from dict
            vtype_raw = char_data.get("value_type", "bytes")
            if isinstance(vtype_raw, str):
                value_type = ValueType(vtype_raw)
            elif isinstance(vtype_raw, ValueType):
                value_type = vtype_raw
            else:
                value_type = ValueType.BYTES
            characteristics[char_uuid] = CharacteristicInfo(
                uuid=char_uuid,
                name=char_data.get("name", ""),
                unit=char_data.get("unit", ""),
                value_type=value_type,
                properties=char_data.get("properties", []),
            )
        service = GattServiceRegistry.create_service(uuid, characteristics)
        if service:
            self._services[str(uuid)] = service

register_custom_characteristic_class

register_custom_characteristic_class(uuid_or_name: str, cls: type[BaseCharacteristic], metadata: CharacteristicRegistration | None = None, override: bool = False) -> None

Register a custom characteristic class at runtime.

Parameters:

Name Type Description Default
uuid_or_name str

The characteristic UUID or name

required
cls type[BaseCharacteristic]

The characteristic class to register

required
metadata CharacteristicRegistration | None

Optional metadata dataclass with name, unit, value_type, summary

None
override bool

Whether to override existing registrations

False

Raises:

Type Description
TypeError

If cls does not inherit from BaseCharacteristic

ValueError

If UUID conflicts with existing registration and override=False

Source code in src/bluetooth_sig/core/translator.py
def register_custom_characteristic_class(
    self,
    uuid_or_name: str,
    cls: type[BaseCharacteristic],
    metadata: CharacteristicRegistration | None = None,
    override: bool = False,
) -> None:
    """Register a custom characteristic class at runtime.

    Args:
        uuid_or_name: The characteristic UUID or name
        cls: The characteristic class to register
        metadata: Optional metadata dataclass with name, unit, value_type, summary
        override: Whether to override existing registrations

    Raises:
        TypeError: If cls does not inherit from BaseCharacteristic
        ValueError: If UUID conflicts with existing registration and override=False

    """
    # Register the class
    CharacteristicRegistry.register_characteristic_class(uuid_or_name, cls, override)

    # Register metadata if provided
    if metadata:
        # Convert ValueType enum to string for registry storage
        vtype_str = metadata.value_type.value
        entry = CustomUuidEntry(
            uuid=metadata.uuid,
            name=metadata.name or cls.__name__,
            id=metadata.id,
            summary=metadata.summary,
            unit=metadata.unit,
            value_type=vtype_str,
        )
        uuid_registry.register_characteristic(entry, override)

register_custom_service_class

register_custom_service_class(uuid_or_name: str, cls: type[BaseGattService], metadata: ServiceRegistration | None = None, override: bool = False) -> None

Register a custom service class at runtime.

Parameters:

Name Type Description Default
uuid_or_name str

The service UUID or name

required
cls type[BaseGattService]

The service class to register

required
metadata ServiceRegistration | None

Optional metadata dataclass with name, summary

None
override bool

Whether to override existing registrations

False

Raises:

Type Description
TypeError

If cls does not inherit from BaseGattService

ValueError

If UUID conflicts with existing registration and override=False

Source code in src/bluetooth_sig/core/translator.py
def register_custom_service_class(
    self,
    uuid_or_name: str,
    cls: type[BaseGattService],
    metadata: ServiceRegistration | None = None,
    override: bool = False,
) -> None:
    """Register a custom service class at runtime.

    Args:
        uuid_or_name: The service UUID or name
        cls: The service class to register
        metadata: Optional metadata dataclass with name, summary
        override: Whether to override existing registrations

    Raises:
        TypeError: If cls does not inherit from BaseGattService
        ValueError: If UUID conflicts with existing registration and override=False

    """
    # Register the class
    GattServiceRegistry.register_service_class(uuid_or_name, cls, override)

    # Register metadata if provided
    if metadata:
        entry = CustomUuidEntry(
            uuid=metadata.uuid,
            name=metadata.name or cls.__name__,
            id=metadata.id,
            summary=metadata.summary,
        )
        uuid_registry.register_service(entry, override)

validate_characteristic_data

validate_characteristic_data(uuid: str, data: bytes) -> ValidationResult

Validate characteristic data format against SIG specifications.

Parameters:

Name Type Description Default
uuid str

The characteristic UUID

required
data bytes

Raw data bytes to validate

required

Returns:

Type Description
ValidationResult

ValidationResult with validation details

Source code in src/bluetooth_sig/core/translator.py
def validate_characteristic_data(self, uuid: str, data: bytes) -> ValidationResult:
    """Validate characteristic data format against SIG specifications.

    Args:
        uuid: The characteristic UUID
        data: Raw data bytes to validate

    Returns:
        ValidationResult with validation details

    """
    try:
        # Attempt to parse the data - if it succeeds, format is valid
        parsed = self.parse_characteristic(uuid, data)
        return ValidationResult(
            uuid=BluetoothUUID(uuid),
            name=parsed.name,
            is_valid=parsed.parse_success,
            actual_length=len(data),
            error_message=parsed.error_message,
        )
    except Exception as e:  # pylint: disable=broad-exception-caught
        # If parsing failed, data format is invalid
        return ValidationResult(
            uuid=BluetoothUUID(uuid),
            name="Unknown",
            is_valid=False,
            actual_length=len(data),
            error_message=str(e),
        )

Quick Examples

Parse Characteristic Data

from bluetooth_sig import BluetoothSIGTranslator

translator = BluetoothSIGTranslator()

# Parse battery level - returns CharacteristicData
result = translator.parse_characteristic("2A19", bytearray([85]))
print(f"Battery: {result.value}%")  # Battery: 85%
print(f"Unit: {result.info.unit}")  # Unit: %

The parse_characteristic method returns a CharacteristicData object.

UUID Resolution

# Resolve UUID to get information
service_info = translator.get_sig_info_by_uuid("180F")
print(service_info.name)  # "Battery Service"

# Resolve characteristic
char_info = translator.get_sig_info_by_uuid("2A19")
print(char_info.name)  # "Battery Level"

See get_sig_info_by_uuid for full details.

battery_level = translator.get_sig_info("Battery Level")

Name Resolution

# Resolve name to UUID
battery_service = translator.get_sig_info_by_name("Battery Service")
print(battery_service.uuid)  # "180F"

battery_level = translator.get_sig_info_by_name("Battery Level")
print(battery_level.uuid)  # "2A19"

Error Handling

from bluetooth_sig.gatt.exceptions import (
    UUIDResolutionError,
    InsufficientDataError,
    ValueRangeError,
)

try:
    result = translator.parse_characteristic("2A19", data)
except UUIDResolutionError:
    print("Unknown UUID")
except InsufficientDataError:
    print("Data too short")
except ValueRangeError:
    print("Value out of range")

See Also

Type Definitions

These types are returned by the core API methods:

bluetooth_sig.types.CharacteristicData

Bases: Struct

Parsed characteristic data with validation results.

Provides structured error reporting with field-level diagnostics and parse traces to help identify exactly where and why parsing failed.

NOTE: This struct intentionally has more attributes than the standard limit to provide complete diagnostic information. The additional fields (field_errors, parse_trace) are essential for actionable error reporting and debugging.

descriptors class-attribute instance-attribute

descriptors: dict[str, DescriptorData] = field(default_factory=dict)

error_message class-attribute instance-attribute

error_message: str = ''

field_errors class-attribute instance-attribute

field_errors: list[ParseFieldError] = field(default_factory=list)

info instance-attribute

name property

name: str

Get the characteristic name from info.

parse_success class-attribute instance-attribute

parse_success: bool = False

parse_trace class-attribute instance-attribute

parse_trace: list[str] = field(default_factory=list)

properties property

properties: list[GattProperty]

Get the properties as strings for protocol compatibility.

raw_data class-attribute instance-attribute

raw_data: bytes = b''

source_context class-attribute instance-attribute

source_context: CharacteristicContext = field(default_factory=CharacteristicContext)

unit property

unit: str

Get the characteristic unit from info.

uuid property

uuid: BluetoothUUID

Get the characteristic UUID from info.

value class-attribute instance-attribute

value: Any | None = None

bluetooth_sig.types.CharacteristicInfo

Bases: SIGInfo

Information about a Bluetooth characteristic.

description class-attribute instance-attribute

description: str = ''

name instance-attribute

name: str

properties class-attribute instance-attribute

properties: list[GattProperty] = field(default_factory=list)

unit class-attribute instance-attribute

unit: str = ''

uuid instance-attribute

uuid: BluetoothUUID

value_type class-attribute instance-attribute

value_type: ValueType = UNKNOWN

bluetooth_sig.types.ServiceInfo

Bases: SIGInfo

Information about a Bluetooth service.

characteristics class-attribute instance-attribute

characteristics: list[CharacteristicInfo] = field(default_factory=list)

description class-attribute instance-attribute

description: str = ''

name instance-attribute

name: str

uuid instance-attribute

uuid: BluetoothUUID

bluetooth_sig.types.ValidationResult

Bases: SIGInfo

Result of data validation.

actual_length class-attribute instance-attribute

actual_length: int | None = None

description class-attribute instance-attribute

description: str = ''

error_message class-attribute instance-attribute

error_message: str = ''

expected_length class-attribute instance-attribute

expected_length: int | None = None

is_valid class-attribute instance-attribute

is_valid: bool = True

name instance-attribute

name: str

uuid instance-attribute

uuid: BluetoothUUID